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

Edited 5 Years Ago by GadiK: n/a

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";
}
This question has already been answered. Start a new discussion instead.