question

OSD-4642 avatar image
0 Votes"
OSD-4642 asked OSD-4642 answered

PowerShell commands and VB.Net Application

Hi,

I have following tasks and currently I am able to perform required tasks using PowerShell as:



  • PowerShell >

  • Rename-LocalUser -Name LocalAdmin -NewName LAdmin -ErrorAction SilentlyContinue

Following code I am using but desired action isn't performed by the code, no errors either.

 Dim p As Process = New Process()
         p.StartInfo.FileName = "PowerShell.exe"
         p.StartInfo.Arguments = "Rename-LocalUser -Name LocalAdmin -NewName LAdmin -ErrorAction SilentlyContinue -windowstyle hidden "
         p.StartInfo.UseShellExecute = False
         p.StartInfo.CreateNoWindow = True
         p.StartInfo.RedirectStandardError = True
         p.Start()
         p.WaitForExit()
         Dim sStdErr_psRename As String = p.StandardError.ReadToEnd()
         Console.WriteLine("Exit code : {0}", p.ExitCode)
         Console.WriteLine("StdErr : {0}", sStdErr_psRename)


Another task that I am currently performing using CMD is to change the password from command line as:
net user %UserName% NewPassword

But same as above, following code didn't performed desired task:

 Dim cUsrPsw As Process = New Process()
         cUsrPsw.StartInfo.FileName = "net.exe"
         cUsrPsw.StartInfo.Arguments = "user %UserName% NewPassword"
         cUsrPsw.StartInfo.UseShellExecute = False
         cUsrPsw.StartInfo.CreateNoWindow = True
         cUsrPsw.StartInfo.RedirectStandardError = True
         cUsrPsw.Start()
         cUsrPsw.WaitForExit()
         Dim sStdErr_cUsrPsw As String = cUsrPsw.StandardError.ReadToEnd()
         Console.WriteLine("Exit code : {0}", cUsrPsw.ExitCode)
         Console.WriteLine("StdErr : {0}", sStdErr_cUsrPsw)


dotnet-visual-basic
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Castorix31 avatar image
0 Votes"
Castorix31 answered Castorix31 commented

This test with PowerShell by adapting your code works for me (Windows 10) as Admin (Manifest with level="requireAdministrator")

 Dim bWow64 As Boolean = False
 IsWow64Process(System.Diagnostics.Process.GetCurrentProcess().Handle, bWow64)
 If (bWow64) Then
     Dim OldValue As IntPtr = IntPtr.Zero
     Dim bReturn As Boolean = Wow64DisableWow64FsRedirection(OldValue)
 End If
 Dim p As Process = New Process()
 p.StartInfo.FileName = "PowerShell.exe"
 p.StartInfo.Arguments = "Rename-LocalUser -Name LocalAdmin -NewName LAdmin"
 p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
 p.StartInfo.UseShellExecute = False
 p.StartInfo.CreateNoWindow = True
 p.StartInfo.RedirectStandardError = True
 p.Start()
 p.WaitForExit()
 Dim sStdErr_psRename As String = p.StandardError.ReadToEnd()
 Console.WriteLine("Exit code : {0}", p.ExitCode)
 Console.WriteLine("StdErr : {0}", sStdErr_psRename)

Declarations :

 <DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
 Public Shared Function IsWow64Process(ByVal hProcess As IntPtr, <Out> ByRef Wow64Process As Boolean) As Boolean
 End Function
    
 <DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
 Public Shared Function Wow64DisableWow64FsRedirection(<Out> ByRef OldValue As IntPtr) As Boolean
 End Function




· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Strange, it worked for you?
It not working for me on Windows 20H2 and I am administrator.

0 Votes 0 ·

Yes, on Windows 10 1909
I tested with an account named "toto" renamed into "titi"
and when I checked in Powershell with Get-LocalUser, I got "titi"

0 Votes 0 ·
Castorix31 avatar image
1 Vote"
Castorix31 answered Castorix31 edited

Otherwise, you can use one of the other methods like Net APIs.
Test on Windows 10 1909 as Admin =>

 Dim ui As USER_INFO_0 = New USER_INFO_0()
 Dim sOldUser As String = "toto", sNewUser As String = "titi"
 ui.usri0_name = sNewUser
 Dim pUI As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(USER_INFO_0)))
 Marshal.StructureToPtr(ui, pUI, False)
 Dim nError As UInteger = 0
 Dim nReturn = NetUserSetInfo(Nothing, sOldUser, 0, pUI, nError)
 If (nReturn <> 0) Then
     Dim sErrorMessage As String = New System.ComponentModel.Win32Exception(nReturn).Message
     System.Windows.Forms.MessageBox.Show("Error : " & nReturn.ToString() & Environment.NewLine & sErrorMessage & Environment.NewLine & "User name : " & sOldUser, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
 Else
     System.Windows.Forms.MessageBox.Show("User : " & sOldUser & Environment.NewLine & "renamed into : " & sNewUser, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
 End If
 Marshal.FreeHGlobal(pUI)

Declarations :


 <DllImport("NetApi32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
 Public Shared Function NetUserSetInfo(servername As String, username As String, level As UInteger, buf As IntPtr, ByRef parm_err As UInteger) As Integer
 End Function
    
 <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
 Public Structure USER_INFO_0
     Public usri0_name As String
 End Structure





· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks @Castorix31
Your method works flawlessly for me. In my original question, PS was working fine but not .Net application, appreciated.

  1. Can we further customize the code to check / execute only if user "toto" exists? else there is no need to try to rename.?

  2. net user %UserName% NewPassword is working fine from command prompt. however, not performing desired action when I use following code:

    Dim cUsrPsw As Process = New Process()
    cUsrPsw.StartInfo.FileName = "net.exe"
    cUsrPsw.StartInfo.Arguments = "user %UserName% NewPassword"
    cUsrPsw.StartInfo.UseShellExecute = False
    cUsrPsw.StartInfo.CreateNoWindow = True
    cUsrPsw.StartInfo.RedirectStandardError = True
    cUsrPsw.Start()
    cUsrPsw.WaitForExit()
    Dim sStdErr_cUsrPsw As String = cUsrPsw.StandardError.ReadToEnd()
    Console.WriteLine("Exit code : {0}", cUsrPsw.ExitCode)
    Console.WriteLine("StdErr : {0}", sStdErr_cUsrPsw)

Any thoughts?

0 Votes 0 ·
  1. You can check if the user exists :

             Dim sCurrentUser As String = "totoa"
             Dim ui As USER_INFO_0 = New USER_INFO_0()
             Dim pUI As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(USER_INFO_0)))
             Marshal.StructureToPtr(ui, pUI, False)
             Dim nReturn = NetUserGetInfo(Nothing, sCurrentUser, 0, pUI)
             If (nReturn <> NERR_UserNotFound) Then
                 ' code to rename user
             End If
    

Declarations

 <DllImport("NetApi32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
 Public Shared Function NetUserGetInfo(servername As String, username As String, level As UInteger, ByRef buf As IntPtr) As Integer
 End Function

 Public Const NERR_BASE = 2100
 Public Const NERR_UserNotFound = (NERR_BASE + 121) ' The user name could not be found.



0 Votes 0 ·

2.
Have you tried to disable Wow redirection first like i my test (Wow64DisableWow64FsRedirection)
or with a fixed username (instead of %UserName% for the current user) ?

(I did not try atm to avoid resetting my own password...)

Otherwise, there is NetUserChangePassword which should work


0 Votes 0 ·
OSD-4642 avatar image
0 Votes"
OSD-4642 answered

Thanks for providing working example.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.