This question has already been solved
You
I have 2 Windows machines. One physical for development and another (virtual) for testing.
I want to write a PERL script that would take my compiled files and copy them to predefined locations on the virtual machine (backing up existing files).
Before copying the files I need to check for certain services and processes and kill them (start them back up at the end of the script).
I can't seem to find any real example for this on the web. Here and there I found people who use Net SCP for similar tasks but my PERL installation doesn't have and I get errors when installing it.
I was hoping to get a good direction and sound advice as to which modules I should try to use.
Thank you very much
This is what I have come up with so far:
#! /usr/bin/perl
use warnings;
use strict;
use File::Copy;
use Win32::OLE qw(in);
use constant wbemFlagReturnImmediately => 0x10;
use constant wbemFlagForwardOnly => 0x20;
my $remotehostip = "192.168.10.102";
my $username = "myUserName";
my $password = "myPassword";
my $localdir = "c:\\localdir";
my $localfilename = "myfilename";
#1. connect to remote host
my $objWMIService = connect_to_remote_host($remotehostip, $username, $password);
#2. check (on remote host) for running service and stop it.
stop_remote_server_service($objWMIService);
#3. copy file from local machine to remote host
copy("$localdir\\$localfilename","\\\\$remotehostip\\$destinationdir") or die "Copy failed: $!";
#connect to remote host WMI service
#params: remote ip (IPv4), user name, user password
#return: remote host WMI service
sub connect_to_remote_host{
my $remotehostip = shift(@_);
my $username = shift(@_);
my $password = shift(@_);
#check remote ip validity (IPv4)
die "remote IP is invalid: $remotehostip" unless $remotehostip =~ /^\d+\.\d+\.\d+\.\d+$/;
my $locatorObj =Win32::OLE->new("WbemScripting.SWbemLocator") or die "ERROR CREATING OBJ";
$locatorObj->{Security_}->{impersonationlevel} = 3;
my $objWMIService = $locatorObj->ConnectServer($remotehostip, "root\\cimv2", $username, $password)
or die "WMI connection failed.\n", Win32::OLE->LastError;
print "connected to remote host $remotehostip\n";
return $objWMIService;
}
#Checks for running service on remote host. Stops the service if it is running.
#params: remote WMI service
sub stop_remote_server_service{
my $objWMIService = shift(@_);
my $cpService = $objWMIService->ExecQuery("SELECT * FROM Win32_Service Where Name=\'MySercieName\'", "WQL",
wbemFlagReturnImmediately | wbemFlagForwardOnly);
#we expect only one result
foreach my $objItem (in $cpService) {
if ($objItem->{State} eq 'Running')
{
my $Result = $objItem->StopService();
if( 0 != $Result ){
die "Failed to stop MySercieName service on remote host";
}
print "Stopped service $objItem->{Name} on remote host\n";
}
return;
}
die "Couldn't find MyServiceName service.";
}
This works fine.
Now I'm stuck with creating a new process on the remote host. I want to run a batch file on the remote machine that performs certain tasks.
When I run the create function I get a PID but I don't see anything happening on the remote host.
Here's the code. Could really use your help here guys.
my $remotehostip = "192.168.10.102";
my $username = "myUserName";
my $password = "myPassword";
my $locatorObj =Win32::OLE->new("WbemScripting.SWbemLocator") or die "ERROR CREATING OBJ";
$locatorObj->{Security_}->{impersonationlevel} = 3; #impersonate
my $objWMIService = $locatorObj->ConnectServer($remotehostip, "root\\cimv2", $username, $password)
or die "WMI connection failed.\n", Win32::OLE->LastError;
print "connected to remote host $remotehostip\n";
#my $command_path = "c:\\test.bat";
my $pid = Variant( VT_I4 | VT_BYREF, 0 );
my $wmiProcessesObj = $objWMIService->Get( "Win32_Process" ) or die "Unable to get the process list:" . Win32::OLE->LastError();
my $error = $wmiProcessesObj->Create($command_path,undef,undef,$pid);
if ($error) {
print "$command_path failed to start with WMI err $error\n", Win32::OLE->LastError;
}else{
print "Started $command_path pid: $pid\n";
}
Thanks,
Gadi K
Alright. Figured out the remote process startup using WMI:
my $remotehostip = "192.168.10.102";
my $username = "myUserName";
my $password = "myPassword";
my $locatorObj =Win32::OLE->new("WbemScripting.SWbemLocator") or die "ERROR CREATING OBJ";
$locatorObj->{Security_}->{impersonationlevel} = 3; #impersonate
my $objWMIService = $locatorObj->ConnectServer($remotehostip, "root\\cimv2", $username, $password) or die "WMI connection failed.\n", Win32::OLE->LastError;
print "connected to remote host $remotehostip\n";
my $wmiProcessesObj = $objWMIService->Get( "Win32_Process" ) or die "Unable to get the process list:" . Win32::OLE->LastError();
my $methodObj = $wmiProcessesObj->Methods_("Create");
my $objInParams = $methodObj->{InParameters};
$objInParams->SpawnInstance_;
my $objInParamsProperties = $objInParams->{Properties_};
$objInParamsProperties->{"CommandLine"} = "c:\\test.bat";
$objInParamsProperties->{"CurrentDirectory"} = "c:\\";
my $objOutParams = $objWMIService->ExecMethod("Win32_Process", "Create", $objInParams);
print "created process pid: $objOutParams->{ProcessId}";The code I presented earlier isn't good enough. The process that is started dies after a minute or so. We can fix this by using Win32_ProcessStartup class and defining the create flags to: Create_New_Console | CREATE_BREAKAWAY_FROM_JOB.
Plus, this time I'm not using reflection:
my $remotehostip = "192.168.10.102";
my $username = "myUserName";
my $password = "myPassword";
my $locatorObj =Win32::OLE->new("WbemScripting.SWbemLocator") or die "ERROR CREATING OBJ";
$locatorObj->{Security_}->{impersonationlevel} = 3; #impersonate
my $objWMIService = $locatorObj->ConnectServer($remotehostip, "root\\cimv2", $username, $password)
or die "WMI connection failed.\n", Win32::OLE->LastError;
print "connected to remote host $remotehostip\n";
my $commandline = ""c:\\test.bat";";
my $currentdirectory = "c:\\";
my $pid = Variant( VT_I4 | VT_BYREF, 0 );
my $wmiProcessesObj = $objWMIService->Get( "Win32_Process" ) or die "Unable to get the process list:" . Win32::OLE->LastError();
my $Startup_Class = $objWMIService->Get("Win32_ProcessStartup");
my $Startup_Config = $Startup_Class->SpawnInstance_ ;
$Startup_Config->{CreateFlags} = 0x1000010;
my $error = $wmiProcessesObj->Create($commandline,$currentdirectory,$Startup_Config,$pid);
if ($error) {
print "$commandline failed to start with WMI err $error\n", Win32::OLE->LastError;
}else{
print "Started $commandline pid: $pid\n";
}