(Remote) VBS/Batch Writing/Execution

Re: (Remote) Batch Writing/Execution

Now as per the concept of running something on an external Windows session, or user login as most people will recognize it as... For NT versions of 6.* (anything from Vista to Windows 8 for now)... Usually it's a matter of cloning a token of for an instance of winlogon.exe. What winlogon.exe is, is basically what keeps and maintains your current windows session. Kill that, and you're basically logged out. This raises interesting questions...

Since there is only one file on your harddrive, winlogon.exe, yet we can start numerous sessions with just this one file, then how does this one file determine what user logon session we log into when we select and login to a windows account? Simply by some data being given to it for when it's instantiated, in short words...

In order to start a process in your current session as LocalSystem though, you will need to replicate an instance of winlogon.exe, however you should not be able to start a process into a different session even if you are LocalSystem when outside of session 0. Because the real LocalSystem running on session 0 is already existent. There can't be 2 session 0's.

Historical methods to achieve this regardless, has been to temporarily install and start a Windows service and launch the program from there, thus allowing the service to decide and manage things on that session for you, along with other sessions if this session (session 0) has permission to manage other session/accounts. Therefore, through this methodology, you will get to permission to administer tasks and run programs across other sessions as well, as long as the active windows service can deal with what you are wanting to do. PsExec uses this trick.

Now instead of that, you could actually start a remote thread, and inject machine code into a virtual address block for a given process running on the session 0 mentioned earlier, and execute it all from there. You'd inherently have permissions identical to whatever the host process had permissions for. Bypassing the need for a windows service, and executing the code directly without having to start a new process.

A bit complex, but that's the gist of it.
 
Last edited:
Re: (Remote) Batch Writing/Execution

Some useful Windows API's to look at:

CreateProcessWithLogonW - http://msdn.microsoft.com/en-us/library/windows/desktop/ms682431(v=vs.85).aspx

Others:
LogonUser - http://msdn.microsoft.com/en-us/library/windows/desktop/aa378184(v=vs.85).aspx
CreateProcessWithTokenW - http://msdn.microsoft.com/en-us/library/windows/desktop/ms682434(v=vs.85).aspx
CreateProcessAsUser - http://msdn.microsoft.com/en-us/library/windows/desktop/ms682429(v=vs.85).aspx

If you choose to move to something like C++. In order for things like this to work though, as i've said, you'd need a handle on the session token for the specified user that you want to run the command or process for, in order to actually do anything. A token is this information as an object reference, that allows you to see what session you're dealing with on the specified user account.

Some example code I wrote:
Code:
LPCWSTR User = L"USER";
LPCWSTR Domain = L"DOMAIN";

HANDLE TokenH;
BOOL result = LogonUser(User, Domain, NULL, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &TokenH);
std::cout << (result ? "Successful logon!" : "Failed to logon...") << std::endl;
std::cin.get();
return 0;
 
Last edited:
Re: (Remote) Batch Writing/Execution

We can try logging into the Guest account if enabled as a demonstration:
Code:
int _tmain(int argc, _TCHAR* argv[])
{
	LPCWSTR User = L"Guest";
	LPCWSTR Domain = L"DOMAIN";

	HANDLE TokenH;
	BOOL result = LogonUser(User, Domain, NULL, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &TokenH);

	printf_s("%s logon attempt.\nToken Handle: %d", 
		result ? "Successful" : "Failed",
		result ? &TokenH : 0);
	
	std::cin.get();
	return 0;
}

I tested this on x64 Windows 8 Pro with success..
 
Last edited:
Re: (Remote) Batch Writing/Execution

Alright, I'm going to apologize now, as I can tell just how intoxicated I am. But having just read your response(s), I understand that you have a LOT more understanding of batch and the Microsoft OS' than I do. As such, I will wait until Monday, when I'm properly in a decent state of mind, to reread your posts, though I do appreciate your providing them (I'm sorry, my brother having company has driven my insanity to the need to drink).

As for the initial code you provided, altering the tokens allowed the code to run, though it took several minute to process, even from a machine on the same domain controller. Overall, this is still a improvement, considering that, once I integrate the network printers, it'll cover half of the entire process, that's quite an improvement, thank you.

Now, when I don't have to reread my typing five times just to correct the mistakes I have corrected, I should edit this post to provide a better response. Unless someone else has already replied, in which case I'll reply to them. ^^'

I need some water...what am I saying? I don't know, but I just hit three spaces as if they were periods in my standard "..." manner. ^^'

*post*
 
Re: (Remote) Batch Writing/Execution

Alright, well revisit this thread and see what works, or to inform us that something doesn't work. If you need to upgrade to the VBS equivalent, I can do that as well, since it should be more compatible than going over to something like Powershell... Although a bit more powerful than Batch in turn as well.

As for what I posted in terms of the C++ stuff here. Now that i've had time to fool around with some various methods and actually compile and debug certain bits of code that I wrote. I think it can be simplified; not all of the API's i've suggested need to be used, however, optionally, they can be used. Impersonation, and security tokens... I can logon to my Guest account and perform various tasks through a bit of C++ code I wrote, although it's still in the beginner stages.
 
Last edited:
Re: (Remote) Batch Writing/Execution

Alright, finished... So what is happening here is i'm able to authenticate or create a replicate of the token data in which defines our Guest account, and create a process with that information to run on the current session, but practically act as though we're running on the Guest account from my current session (my main account, not the Guest account). Like the merger of 2 sessions into 1, i'm able to be doing anything I want on the duplicate Guest account session from my main session.

L0BSU.gif


NOTE: For the demonstration above in the bad quality gif, I executed the cmd.exe process and sent it these command line arguments:
Code:
/k echo Environment Var ^%USERNAME^% = %USERNAME%
 
Re: (Remote) Batch Writing/Execution

Video Demonstration:

Unfortunately, logging out and/or switching users to my Guest account to show you the file on the desktop and all of that, isn't possible without recording my screen from a camera, so I had to end the video there.
 
Last edited:
Re: (Remote) Batch Writing/Execution

Alright, I got it to export the network printer locations, but it won't save to a location unless I provide the FQP. I'm trying to use the %USERPROFILE% variable, which automatically redirects in Explorer, but it won't work in this batch, it doesn't error, it just doesn't save. :S

Code:
@ECHO OFF && SETLOCAL EnableDelayedExpansion

CALL :GetIdentifiers

ECHO Exporting data for '%USER%' with SID:%SID%...
REG EXPORT HKU\%SID%\Network "%USERPROFILE%\Desktop\Network Drives.reg"
REG EXPORT HKU\%SID%\Printers "%USERPROFILE%\Desktop\Network Printers1.reg"
REG EXPORT "HKU\%SID%\Software\Microsoft\Windows NT\CurrentVersion\Devices" "%USERPROFILE%\Desktop\Network Printers2.reg"
REG EXPORT "HKU\%SID%\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts" "%USERPROFILE%\Desktop\Network Printers3.reg"

PAUSE && GOTO :EOF

:GetIdentifiers
CALL :GetUser && CALL :GetUserSID
goto :EOF

:GetUser
for /f "tokens=2 skip=1 delims=\ " %%G IN ('"wmic computersystem get Username"') DO (
	set USER=%%G&& goto :EOF
)

:GetUserSID
FOR /F "skip=1" %%G IN ('"wmic path win32_useraccount where name='%USER%' get sid"') DO (
   SET SID=%%G&& GOTO :EOF
)

Any ideas?



Edit:
On the note of the VBS alternative, I'm strongly considering it due to the ease it would provide for running the scripts remotely, instead of having to remote into the machine, as well as the added ability to include the PST mappings through VBS, something not accessible with batch. ^^'
 
Re: (Remote) Batch Writing/Execution

I thought you wanted to use wmic (for a WMI query) to retrieve the username instead of using %username% though?
 
Re: (Remote) Batch Writing/Execution

No, not the username variable, the %USERPROFILE% variable. On the Win XP machines, these are stored in D:\Documents and Settings whereas our Win 7 machines store them in C:\Users.

Now that I think about it, I'd run into the same issue with the profile variable as I did the username. So, instead my challange is to distinguish the OS' and make it into an "if xp then xxx else if 7 then yyy else error".

Alright, so, I got a code build for determining the OS', but integration to your work is another story.

Code:
@echo off

ver | find "XP" > nul
if %ERRORLEVEL% == 0 goto ver_xp

if not exist %SystemRoot%\system32\systeminfo.exe goto warnthenexit

systeminfo | find "OS Name" > %TEMP%\osname.txt
FOR /F "usebackq delims=: tokens=2" %%i IN (%TEMP%\osname.txt) DO set vers=%%i

echo %vers% | find "Windows 7" > nul
if %ERRORLEVEL% == 0 goto ver_7

goto warnthenexit

:ver_7
:Run Windows 7 specific commands here.
set os = win7
goto exit

:ver_xp
:Run Windows XP specific commands here.
set os = winxp
goto exit

:warnthenexit
echo Machine undetermined.

:exit

This is not my code, only modified to remove the versions I don't need and to reflect setting a variable "os" to distinguish in the if..then..else statement(s).

Now, alone this works just fine with distinguishing the OS, but I'm not sure how I would merge it with your own code. I tried placing it up top, removing the :exit, and changing the goto exit to goto GOF, but no luck there. :S
 
Re: (Remote) Batch Writing/Execution

Code:
@echo off

ver | find "XP" > nul
if %ERRORLEVEL% == 0 goto ver_xp

if not exist %SystemRoot%\system32\systeminfo.exe goto warnthenexit

systeminfo | find "OS Name" > %TEMP%\osname.txt
FOR /F "usebackq delims=: tokens=2" %%i IN (%TEMP%\osname.txt) DO set vers=%%i

echo %vers% | find "Windows 7" > nul
if %ERRORLEVEL% == 0 goto ver_7

goto warnthenexit

:ver_7
:Run Windows 7 specific commands here.
set os = win7
goto Begin

:ver_xp
:Run Windows XP specific commands here.
set os = winxp
goto Begin

:warnthenexit
echo Machine undetermined.

goto Finish

:Begin

::------------------
::My Code Here
::Check %os% for winxp or win7
::------------------

:Finish
::Do something in the case not Windows 7 or XP Here... If anything
 
Re: (Remote) Batch Writing/Execution

Alright, this is starting to give me a headache. I think I will switch to VBS now. Following your instructions, I was able to run the script, but it won't "detect" the supplied path.

I have all of Thursday and Friday at work with few calls, so I'll be reading up on VBS then, hopefully post an attempt to convert what we have so far.

In case you're interested, here's the modified batch which produces "Error: The system was unable to find the specified registry key or value" for all four export commands. *sigh*

Code:
@echo off

ver | find "XP" > nul
if %ERRORLEVEL% == 0 goto ver_xp

if not exist %SystemRoot%\system32\systeminfo.exe goto warnthenexit

systeminfo | find "OS Name" > %TEMP%\osname.txt
FOR /F "usebackq delims=: tokens=2" %%i IN (%TEMP%\osname.txt) DO set vers=%%i

echo %vers% | find "Windows 7" > nul
if %ERRORLEVEL% == 0 goto ver_7

goto warnthenexit

:ver_7
:Run Windows 7 specific commands here.
set PATH = "C:\Users\%USER%\"
goto Begin

:ver_xp
:Run Windows XP specific commands here.
set PATH = "D:\Documents and Settings\%USER%\"
goto Begin

:warnthenexit
echo Machine undetermined.

goto Finish

:Begin

CALL :GetIdentifiers

ECHO Exporting data for '%USER%' with SID:%SID%...
REG EXPORT HKU\%SID%\Network "%PATH%\Network Drives.reg"
REG EXPORT HKU\%SID%\Printers "%PATH%\Network Printers1.reg"
REG EXPORT "HKU\%SID%\Software\Microsoft\Windows NT\CurrentVersion\Devices" "%PATH%\Network Printers2.reg"
REG EXPORT "HKU\%SID%\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts" "%PATH%\Network Printers3.reg"

PAUSE && GOTO :EOF

:GetIdentifiers
CALL :GetUser && CALL :GetUserSID
goto :EOF

:GetUser
for /f "tokens=2 skip=1 delims=\ " %%G IN ('"wmic computersystem get Username"') DO (
	set USER=%%G&& goto :EOF
)

:GetUserSID
FOR /F "skip=1" %%G IN ('"wmic path win32_useraccount where name='%USER%' get sid"') DO (
   SET SID=%%G&& GOTO :EOF
)

:Finish



Edit:
Alright, I've modified it so that it "processes", but I can't get it to work with the defined path, it defaults to root.

Code:
@ECHO OFF && SETLOCAL EnableDelayedExpansion

CALL :GetIdentifiers

:Begin
ECHO Exporting data for '%USER%' with SID '%SID%' to '%STORETOPATH%'...
REG EXPORT HKU\%SID%\Network "%STORETOPATH%\Network Drives.reg"
REG EXPORT HKU\%SID%\Printers "%STORETOPATH%\Network Printers1.reg"
REG EXPORT "HKU\%SID%\Software\Microsoft\Windows NT\CurrentVersion\Devices" "%STORETOPATH%\Network Printers2.reg"
REG EXPORT "HKU\%SID%\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts" "%STORETOPATH%\Network Printers3.reg"

PAUSE && GOTO :EOF

:GetIdentifiers
CALL :GetUser && CALL :GetUserSID && CALL :version_finder
goto :EOF

:GetUser
for /f "tokens=2 skip=1 delims=\ " %%G IN ('"wmic computersystem get Username"') DO (
	set USER=%%G&& goto :EOF
)

:GetUserSID
FOR /F "skip=1" %%G IN ('"wmic path win32_useraccount where name='%USER%' get sid"') DO (
   SET SID=%%G&& GOTO :EOF
)

:version_finder
ver | find "XP" > nul
if %ERRORLEVEL% == 0 goto ver_xp
if not exist %SystemRoot%\system32\systeminfo.exe goto warnthenexit
systeminfo | find "OS Name" > %TEMP%\osname.txt
FOR /F "usebackq delims=: tokens=2" %%i IN (%TEMP%\osname.txt) DO set vers=%%i
echo %vers% | find "Windows 7" > nul
if %ERRORLEVEL% == 0 goto ver_7
goto warnthenexit

:ver_7
set STORETOPATH = "C:\Users\%USER%\"
goto :EOF

:ver_xp
set STORETOPATH = "D:\Documents and Settings\%USER%\"
goto :EOF

:warnthenexit
echo Machine undetermined.
goto Finish

:Finish

I even modified the echo to display the path, but the echo results in: Exporting data for 'chris.esbrandt' with SID 'S-1-5-21-1228493135-1473791447-1069890735-58882' to ''...

So, I'm at another loss. I'm sure I screwed it up, I just don't know how or where. :(
 
Re: (Remote) Batch Writing/Execution

Here you don't need the goto Finish part because it's the next line and the last code you have in this script anyways.
Code:
:warnthenexit
echo Machine undetermined.
goto Finish

:Finish

Also, keep in mind, by setting a variable like this in batch:
Code:
set STORETOPATH = "D:\Documents and Settings\%USER%\"

Not only are you also storing the double quotes, but after the equals sign, where you have a space, this is also added to the variable. So your variable holds this data:
Code:
{SPACE}"D:\Documents and Settings\MYUSERNAME\"

Take note of how I avoided that in my code provided to you earlier :)
Code:
set USER=%%G&& goto :EOF

Try to stay away from spaces after the assignment operator here unless you intend to assign the prefixed " "
to the variable at the front.
 
Re: (Remote) Batch Writing/Execution

Alright, I went ahead and redid this in VBS, since it'll be completed there anyways (could a moderator edit the title to reflect VBS instead of Batch?).

Now, on XP, I can do everything, perfectly. On Windows 7, I ran into issues. All resolved except for one. Bare in mind, at this point, I'm only trying to pull the information, I haven't even started on the regedits.

It seems the SID can't be pulled from Win7 like it can in WinXP, and I'm going to start pulling my hair out because I was able to rewrite for XP VBS in about 30 min., then update all but the SID to work with Win7 in another hour, but I'm going on 3 hours without any luck with the SID.

Code:
Option Explicit
Dim strComputer
Dim objWMI

Dim colItems
Dim objItem
Dim VerBig
Dim OSystem
Dim WSHShell

Dim colItems2
Dim objItem2
Dim arrName
Dim domain
Dim currentUser

Dim colItems3
Dim objItem3
Dim SID
Dim objAccount

Dim storeToPath

' Here is where we interrogate the Operating System
' On Error Resume Next

' Get the computer name (ie . = localhost)
strComputer = InputBox("Computer Name or IP Address: ")

' Remote connection path
Set objWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

' This is where WMI interrogates the operating system
Set colItems = objWMI.ExecQuery("Select * from Win32_OperatingSystem",,48)

' Here we filter Version from the dozens of properties
For Each objItem in colItems
 VerBig = Left(objItem.Version,3)
Next

' Spot VerBig variable in previous section
' Note the output variable is called OSystem

' This is where WMI interrogates the computer system
Set colItems2 = objWMI.ExecQuery("Select * from Win32_ComputerSystem",,48)

Select Case VerBig
 Case "6.1"
  OSystem = "7"
  Set WSHShell = CreateObject("WScript.Shell")
  domain = WshShell.ExpandEnvironmentStrings("%userdomain%")
  currentUser = WshShell.ExpandEnvironmentStrings("%username%")
  Set objAccount = objWMI.Get("Win32_UserAccount.Name='" & currentUser & "',Domain='" & domain & "'")
  SID = objAccount.SID
 Case "5.1"
  OSystem = "XP"
  ' Here we filter UserName from the dozens of properties
  For Each objItem2 in colItems2
   arrName = Split(objItem2.UserName, "\")
   domain = arrName(0)
   currentUser = arrName(1)
   ' This is where WMI interrogates the user account
   ' Set colItems3 = objWMI.ExecQuery("Select * from Win32_UserAccount",,48)
   Set colItems3 = objWMI.ExecQuery("Select * from Win32_Account where Domain='" & domain & "' and Name = '" & currentUser & "'" )

   ' Here we filter SID from the dozens of properties
   For Each objItem3 in colItems3
    SID = objItem3.SID
   Next
  Next
 Case Else OSystem = "Invalid OS"
End Select

' Spot VerBig variable in previous section
' Note the output variable is called storeToPath

Select Case VerBig
 Case "6.1"
  storeToPath = "C:\Users\" & currentUser
 Case "5.1"
  storeToPath = "D:\Documents and Settings\" & currentUser
End Select

Wscript.Echo "Version No: " & VerBig & vbCr _
& "OS System: " & OSystem & vbCr _
& "Save to Path: " & storeToPath & vbCr _
& "User SID: " & SID

WScript.Quit

' End of script

That's the code. Works fine on XP, but I can't get it to work in Win7.

Any ideas would be greatly appreciated (including in improving the structure of the code). VBS, like batch, isn't one of my languages of choice, but I wouldn't call myself a novice either. ^^'

If I can dig up a solution before I get a reply, I'll edit, like usual, to reflect the solution I implemented. ^^



Edit:
I edited the code to reflect the most "promising" attempt for pulling the SID. The reasoning I say it's the most promising is because it's a code that worked for my WinXP machine too (I'd prefer to lessen the code through compatibility), but I left it seperate since it did still fail. It produces a blank result, which causes the script to fail.
 
Quite a bit of Dim's :) Have you tried the comma delimited version? I like to separate similarly used variables by commas... Globals on one line, maybe temp variables on another separated by commas... Example:
Code:
Dim x,y,z

Seems to work fine for me on Windows 8 though with some major version case statement modifications. (Winodws 8 is 6.2, so I had to add that):
V4Gev.png


Though Windows 8 should be uniquely similar to Windows 7 in this way... So lets look at the variants. What are you inputting into that input box? Here's what I was entering in to check my current computer:
Code:
.

Note: This char is just a period/dot.

Also note that you can use a MsgBox in VBS:
Code:
MsgBox "Version No: " & VerBig & vbCr _
& "OS System: " & OSystem & vbCr _
& "Save to Path: " & storeToPath & vbCr _
& "User SID: " & SID, 64, "Information"

Just a bit better looking output:
ayyJe.png


My half-assed revision:
Code:
Option Explicit
Dim objWMI, strComputer

Dim colItems, objItem, VerBig, OSystem, WSHShell
Dim colItems2, objItem2, arrName, domain, currentUser
Dim colItems3, objItem3, SID, objAccount

Dim storeToPath

' Here is where we interrogate the Operating System
' On Error Resume Next

' Get the computer name (ie . = localhost)
strComputer = InputBox("Computer Name or IP Address: ")

' Remote connection path
Set objWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

' This is where WMI interrogates the operating system
Set colItems = objWMI.ExecQuery("Select * from Win32_OperatingSystem",,48)

' Here we filter Version from the dozens of properties
For Each objItem in colItems
	VerBig = Left(objItem.Version,3)
Next

' Spot VerBig variable in previous section
' Note the output variable is called OSystem

' This is where WMI interrogates the computer system
Set colItems2 = objWMI.ExecQuery("Select * from Win32_ComputerSystem",,48)

Select Case VerBig
	Case "6.2"
		OSystem = "8"
		Set WSHShell = CreateObject("WScript.Shell")
		domain = WshShell.ExpandEnvironmentStrings("%userdomain%")
		currentUser = WshShell.ExpandEnvironmentStrings("%username%")
		Set objAccount = objWMI.Get("Win32_UserAccount.Name='" & currentUser & "',Domain='" & domain & "'")
		SID = objAccount.SID
	Case "6.1"
		OSystem = "7"
		Set WSHShell = CreateObject("WScript.Shell")
		domain = WshShell.ExpandEnvironmentStrings("%userdomain%")
		currentUser = WshShell.ExpandEnvironmentStrings("%username%")
		Set objAccount = objWMI.Get("Win32_UserAccount.Name='" & currentUser & "',Domain='" & domain & "'")
		SID = objAccount.SID
	Case "5.1"
		OSystem = "XP"
		' Here we filter UserName from the dozens of properties
		For Each objItem2 in colItems2
			arrName = Split(objItem2.UserName, "\")
			domain = arrName(0)
			currentUser = arrName(1)
			' This is where WMI interrogates the user account
			' Set colItems3 = objWMI.ExecQuery("Select * from Win32_UserAccount",,48)
			Set colItems3 = objWMI.ExecQuery("Select * from Win32_Account where Domain='" & domain & "' and Name = '" & currentUser & "'" )

			' Here we filter SID from the dozens of properties
			For Each objItem3 in colItems3
				SID = objItem3.SID
			Next
		Next
	Case Else OSystem = "Invalid OS"
End Select

' Spot VerBig variable in previous section
' Note the output variable is called storeToPath

Select Case VerBig
	Case "6.1" || "6.2"
		storeToPath = "C:\Users\" & currentUser
	Case "5.1"
		storeToPath = "D:\Documents and Settings\" & currentUser
End Select

MsgBox "Version No: " & VerBig & vbCr _
& "OS System: " & OSystem & vbCr _
& "Save to Path: " & storeToPath & vbCr _
& "User SID: " & SID, 64, "Information"

WScript.Quit

I just edited the Case statements a bit, and the MsgBox.
 
Last edited:
Yeah, I know about the msgbox, I just don't have any care about that. I'm only displaying the information to verify it is pulling the corrent information. Remember, this is only the first half of the first of 3 steps in the ultimate goal of this script. As for the Dims, call it habit.

What I enter into the prompt for a machine name is the machine name. Remember, I'm running XP and am trying to pull the information for a 7 machine. Locally, using ".", "127.0.0.1", "localhost", my machine name, or my IP address all return the correct values. I actually hadn't tried running it directly for a 7 machine. ^^'

Alright, so that changes the problem a bit. I'll try to make this into a table to make it a little easier to understand.
Code:
             Ran To
         ---------------
Ran From | . | XP | 7  |
---------|---|----|----|
      XP | G | G  | E1 |
---------|---|----|----|
       7 | G | E2 | E1 |
------------------------

G = Good
E1 = Error: Not found; Code: 80041002; Source: SWbemServicesEx
E2 = SID is Null
It's kinda hard to test something out when you only have one or two machines and they don't have the right OS' to manipulate them in, but I appreciate all your help in trying. I just wish I could be a little more help on it all. ^^'



Edit:
As a means to try to get several perspectives and hoping find a solution sooner, I posted on TechNet: http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/ad0262e0-4ad9-452a-baf4-0904da09c288

Don't get me wrong, I know these guys are smart and good, but this guy has to be joking to tell me that the code I provided won't run remotely at all. XD



Edit:
I'm a bit in shock after the whole "the provided script can't run remotely" thing, but TechNet gave me the answer, sorta. Maybe they did and I just ain't connecting all the dots of what they said.

Anyways, I've been trying to have the remote computer run the pull of the SID, but it's a network-based account system, making the SID universal across the entire network! I simply modified the SID search to run locally, instead of remotely, and it now work in all senarios from Win XP and Win 7! To make it better, since it's a universal command, I don't have to seperate it, making less code! :D

Code:
Option Explicit
Dim strComputer
Dim objWMI

Dim colItems
Dim objItem
Dim VerBig
Dim OSystem
Dim WSHShell

Dim colItems2
Dim objItem2
Dim arrName
Dim domain
Dim currentUser

Dim colItems3
Dim objItem3
Dim SID
Dim objAccount

Dim storeToPath

' Here is where we interrogate the Operating System
' On Error Resume Next

' Get the computer name (ie . = localhost)
strComputer = InputBox("Computer Name or IP Address: ")

' Remote connection path
Set objWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

' This is where WMI interrogates the operating system
Set colItems = objWMI.ExecQuery("Select * from Win32_OperatingSystem",,48)

' Here we filter Version from the dozens of properties
For Each objItem in colItems
 VerBig = Left(objItem.Version,3)
Next

' Spot VerBig variable in previous section
' Note the output variable is called OSystem

' This is where WMI interrogates the computer system
Set colItems2 = objWMI.ExecQuery("Select * from Win32_ComputerSystem",,48)

Select Case VerBig
 Case "6.1"
  OSystem = "7"
  Set WSHShell = CreateObject("WScript.Shell")
  domain = WshShell.ExpandEnvironmentStrings("%userdomain%")
  currentUser = WshShell.ExpandEnvironmentStrings("%username%")
 Case "5.1"
  OSystem = "XP"
  ' Here we filter UserName from the dozens of properties
  For Each objItem2 in colItems2
   arrName = Split(objItem2.UserName, "\")
   domain = arrName(0)
   currentUser = arrName(1)
  Next
 Case Else OSystem = "Invalid OS"
End Select
  ' This is where WMI interrogates the user account
  Set objAccount = GetObject("winmgmts:root/cimv2:Win32_UserAccount.Domain='" & domain & "'" & ",Name='" & currentUser & "'")
  SID = objAccount.SID

' Spot VerBig variable in previous section
' Note the output variable is called storeToPath
Select Case VerBig
 Case "6.1"
  storeToPath = "C:\Users\" & currentUser
 Case "5.1"
  storeToPath = "D:\Documents and Settings\" & currentUser
End Select

Wscript.Echo "Version No: " & VerBig & vbCr _
& "OS System: " & OSystem & vbCr _
& "Save to Path: " & storeToPath & vbCr _
& "User SID: " & SID

WScript.Quit

' End of script

Now I just need to make the regedits to back-up the information, incorporate PST mappings, a pause while the user logs off, the renaming of the profile remotely(, removal of registry entry in Win 7), another pause while the user logs in and the profile is rebuilt, copy files from the old profile to the new, and restore all those backed up mappings. Joy!
 
For that 80041002 error, could be because the MSI provider is corrupted for that machine's OS. To test this theory, try to fix it or reinstall it.. Another possibility is that you've misspelled an object name in your VB script for the querying. Or that it simply doesn't exist because as you'll see in my reply here below, i'll mention that not all OS's are the same. Another possible reason is mentioned in this link from Microsoft: http://msdn.microsoft.com/en-us/library/windows/desktop/aa394559(v=vs.85).aspx

Code:
0x800410xx - 0x800440: Errors that originate in WMI itself.

A specific WMI operation failed because of

    • An error in the request, for example, a WQL query fails or the account does not have the correct permissions.
    • A WMI infrastructure problem, such as incorrect CIM or DCOM registration.

Therefore, it may be permission issues, or configuration issues as well.

And on that note, when you are doing these tests.. Are you running them on clean OS installs? Or pre-existing OS installations? I would recommend (if you can) running your tests on clean installs to make sure that it's not a local OS related problem, and definitely something with your script instead. It may cause you less headaches :)

Another thing I should point out, if you haven't known this already, is WMI queries for various operating systems in some cases, can differ. So for instance, a query for Windows 7, may not work in XP, and vice versa.

A few words I seen you mention "As the user logs in", so as the account is validated with input credentials? You know the best idea for what you're trying to do then in this case would be to have a system service run all that you're trying to do. Then you can actually have this interconnected to interact over the local network. I'm trying to keep the complexity minimal for you though as I know you're not a super advanced programmer (with this kind of stuff anyway). Or maybe i'm wrong and too quickly assumed that? :thumbsup2: If so I won't be heartbroken, i'd love to see what you could come up with if you knew how to work with system services.

~Ace
 
Last edited:
This post is kinda a go between for work, since I can't e-mail the code to myself. :S

Feel free to critique it, this has added a section for writing a batch to the remote machine using the retreived information that I'll later program to be ran.
Code:
Option Explicit
Dim strComputer
Dim objWMI

Dim colItems
Dim objItem
Dim VerBig
Dim OSystem
Dim WSHShell

Dim colItems2
Dim objItem2
Dim arrName
Dim domain
Dim currentUser

Dim colItems3
Dim objItem3
Dim SID
Dim objAccount

Dim storeToPath

Dim batchStoreToPath
Dim fileSys
Dim batchStorePath
Dim exportBatch

Dim objWMIService
Dim intProcessID
' Here is where we interrogate the Operating System
' On Error Resume Next

' Get the computer name (ie . = localhost)
strComputer = InputBox("Computer Name or IP Address: ")

' Remote connection path
Set objWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

' This is where WMI interrogates the operating system
Set colItems = objWMI.ExecQuery("Select * from Win32_OperatingSystem",,48)

' Here we filter Version from the dozens of properties
For Each objItem in colItems
 VerBig = Left(objItem.Version,3)
Next

' Spot VerBig variable in previous section
' Note the output variable is called OSystem

' This is where WMI interrogates the computer system
Set colItems2 = objWMI.ExecQuery("Select * from Win32_ComputerSystem",,48)

Select Case VerBig
 Case "6.1"
  OSystem = "7"
  Set WSHShell = CreateObject("WScript.Shell")
  domain = WshShell.ExpandEnvironmentStrings("%userdomain%")
  currentUser = WshShell.ExpandEnvironmentStrings("%username%")
 Case "5.1"
  OSystem = "XP"
  ' Here we filter UserName from the dozens of properties
  For Each objItem2 in colItems2
   arrName = Split(objItem2.UserName, "\")
   domain = arrName(0)
   currentUser = arrName(1)
  Next
 Case Else OSystem = "Invalid OS"
End Select
  ' This is where WMI interrogates the user account
  Set objAccount = GetObject("winmgmts:root/cimv2:Win32_UserAccount.Domain='" & domain & "'" & ",Name='" & currentUser & "'")
  SID = objAccount.SID

' Spot VerBig variable in previous section
' Note the output variable is called storeToPath
Select Case VerBig
 Case "6.1"
  storeToPath = "C:\Users\" & currentUser
  Select Case strComputer
   Case ".", "localhost", "127.0.0.1"
    batchStoreToPath = storeToPath
   Case Else
    batchStoreToPath = "\\" & strComputer & "\c$\Users\" & currentUser
  End Select
 Case "5.1"
  storeToPath = "D:\Documents and Settings\" & currentUser
  Select Case strComputer
   Case ".", "localhost", "127.0.0.1"
    batchStoreToPath = storeToPath
   Case Else
    batchStoreToPath = "\\" & strComputer & "\d$\Documents and Settings\" & currentUser
  End Select
End Select

Wscript.Echo "Version No: " & VerBig & vbCr _
& "OS System: " & OSystem & vbCr _
& "Save to Path: " & storeToPath & vbCr _
& "User SID: " & SID

' This is the creation of a batch file on the remote machine to export the registry entries for network mappings
Set fileSys = CreateObject("Scripting.fileSystemObject")
Set batchStorePath = fileSys.GetFolder(batchStoreToPath)
Set exportBatch = batchStorePath.CreateTextFile("export.bat", True)
exportBatch.WriteLine("@ECHO OFF && SETLOCAL EnableDelayedExpansion")
exportBatch.WriteLine("")
exportBatch.WriteLine("ECHO Exporting data for '" & currentUser & "' with SID '" & SID & "' to '" & storeToPath & "'...")
exportBatch.WriteLine("REG EXPORT HKU\" & SID & "\Network " & Chr(34) & storeToPath & "\1.reg" & Chr(34))
exportBatch.WriteLine("REG EXPORT HKU\" & SID & "\Printers " & Chr(34) & storeToPath & "\2.reg" & Chr(34))
exportBatch.WriteLine("REG EXPORT " & Chr(34) & "HKU\" & SID & "\Software\Microsoft\Windows NT\CurrentVersion\Devices" & Chr(34) & " " & Chr(34) & storeToPath & "\3.reg" & Chr(34))
exportBatch.WriteLine("REG EXPORT " & Chr(34) & "HKU\" & SID & "\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts" & Chr(34) & " " & Chr(34) & storeToPath & "\4.reg" & Chr(34))
exportBatch.WriteLine("echo.>>" & Chr(34) & storeToPath & "\Network Mappings.reg" & Chr(34))
exportBatch.WriteLine("type " & Chr(34) & storeToPath & "\1.reg" & Chr(34) & " | find /v " & Chr(34) & "Windows Registry Editor Version 5.00" & Chr(34) & ">>" & Chr(34) & storeToPath & "\Network Mappings.reg" & Chr(34))
exportBatch.WriteLine("type " & Chr(34) & storeToPath & "\2.reg" & Chr(34) & " | find /v " & Chr(34) & "Windows Registry Editor Version 5.00" & Chr(34) & ">>" & Chr(34) & storeToPath & "\Network Mappings.reg" & Chr(34))
exportBatch.WriteLine("type " & Chr(34) & storeToPath & "\3.reg" & Chr(34) & " | find /v " & Chr(34) & "Windows Registry Editor Version 5.00" & Chr(34) & ">>" & Chr(34) & storeToPath & "\Network Mappings.reg" & Chr(34))
exportBatch.WriteLine("type " & Chr(34) & storeToPath & "\4.reg" & Chr(34) & " | find /v " & Chr(34) & "Windows Registry Editor Version 5.00" & Chr(34) & ">>" & Chr(34) & storeToPath & "\Network Mappings.reg" & Chr(34))
exportBatch.WriteLine("del " & Chr(34) & storeToPath & "\1.reg" & Chr(34))
exportBatch.WriteLine("del " & Chr(34) & storeToPath & "\2.reg" & Chr(34))
exportBatch.WriteLine("del " & Chr(34) & storeToPath & "\3.reg" & Chr(34))
exportBatch.WriteLine("del " & Chr(34) & storeToPath & "\4.reg" & Chr(34))
exportBatch.WriteLine("")
exportBatch.WriteLine("PAUSE && GOTO :EOF")
exportBatch.Close

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process") 
objWMIService.Create batchStoreToPath & "\export.bat", Null, Null, intProcessID 

WScript.Quit

' End of script



Edit:
Added a select case so that if you set the computer name as ".", "localhost", or "127.0.0.1" it'll default to a store location corresponding to the local machine, rather than a remote.
Added a merger variation to the batch that is created so that when the restore is done only one file has to be ran instead of 4.

Next up, pulling PST mappings. :D



Edit:
Added remote execution of the created batch.
 

Has Sysnative Forums helped you? Please consider donating to help us support the site!

Back
Top