New-Object -ComObject -Servername - powershell

I wanted to know in PowerShell if there is a way New-Object -ComObject can be run against a remote server like how it's possible natively in VBScript WScript.CreateObject("COM Server", "RemoteServerName").
If not, is there an option without having to rely on PS Remoting technologies?

I don't think it's possible to instantiate remote COM objects via New-Object. You should be able to get the desired result via the GetTypeFromProgID() and CreateInstance() methods, though:
$server = 'RemoteServerName'
$type = [Type]::GetTypeFromProgID('COM Server', $server, $true)
if ($type) {
$obj = [Activator]::CreateInstance($type)
}
[source]

Related

PowerShell - Connect and disconnect from SPO

The script connects to SPO and read from excel. At the end I close the local excel instance and disconnect from SPO. Usually I am running the script so this is really necessary to do it every run? connect ad disconnect. Maybe there is another way to do it? ask if there is a valid active connection?
I saw that if the credentials are wrong for example the script is still reading from the sheet maybe from the memory, how can I protect from this scenario?
#Connecting to SharePoint Online site
Write-host "Connecting to SharePoint Online"
Connect-PnPOnline -Url $SharePointSiteURL # -Credentials $PSCredentials
$ExcelObject = New-Object -ComObject Excel.Application
$ExcelWorkBook = $ExcelObject.Workbooks.Open($SharePointSiteURL)
$ExcelWorkSheet = $ExcelWorkBook.Sheets.Item("VIP List")
function QuitExcel {
# when done, quit Excel and remove the used COM objects from memory (important)
$ExcelWorkBook.Close()
$ExcelObject.Quit()
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ExcelWorkSheet)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ExcelWorkBook)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ExcelObject)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
Disconnect-PnPOnline

Discovery Script is not working

Below is my script with identifiers scrubbed. The Base Class for Diagnostics is MyCompany.MyApp and the base class of that is Windows Computer. If I run this on the target machine directly with parameters I am getting XML returned. If I run from my PC it is blank. That makes sense locally, but I thought when you run discoveries that the agent runs it on the machine you are targeting? All my other discoveries thus far have been registry so it is possible I am doing something completely wrong.
Param($sourceId, $managedEntityId, $ComputerName)
$api = New-Object -ComObject 'MOM.ScriptAPI'
$discoveryData = $api.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)
$Diagnostics = Invoke-Command -ComputerName $ComputerName {
Get-WebApplication -Name "diagnostics"
}
foreach ($x in $Diagnostics)
{
$instance = $discoveryData.CreateClassInstance("$MPElement[Name='MyCompany.MyApp.Diagnostics']$")
$instance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $ComputerName)
$discoveryData.AddInstance($instance)
}
As the first, most obvious reason, you don't output the discovery data onto output stream (StdOut). Just simple add $discoveryData at a new line by the end of your script.
Moreover, more information about your class and MP architecture required. I'd probably recommend you to use Windows!Microsoft.Windows.ComputerRole as base class and host it on target computer object.
Regards
Max

How to modify COM+ applications from powershell

I am automating the creation of a web server. An application is created for me, but I need to manually change the Identity of a COM+ Application to run as a specific user.
Being a linux admin with little experience with powershell, I'm in over my head. It looks like there is an API to modify COM+ applications.
https://msdn.microsoft.com/en-us/library/ms679173(v=vs.85).aspx
From this stackoverflow question, I've gotten this far in modifying the application
$comAdmin = New-Object -comobject COMAdmin.COMAdminCatalog
$apps = $comAdmin.GetCollection(“Applications”)
$apps.Populate();
I am able to see my application in the list by typing in this command
$apps
Is it possible to modify the foobar application Identity from powershell?
Thanks to this stackoverflow question, I got it working.
$targetApp = "examplecompany"
$comAdmin = New-Object -comobject COMAdmin.COMAdminCatalog
$apps = $comAdmin.GetCollection("Applications")
$apps.Populate();
$app = $apps | Where-Object {$_.Name -eq $targetApp}
$comAdmin.ShutdownApplication($targetApp)
$app.Value("Identity") = 'example.com\exampleuser'
$app.Value("Password") = 'correct-horse-battery-staple'
$apps.SaveChanges()
$comAdmin.StartApplication($targetApp)

How to create a com object in another domain?

I'm trying to use PowerShell to quickly find the Scheduled Tasks in the root folder of a remote server. I find all sorts of scripts that others have written, but they're either looking at the localhost or on a server in the same domain. I support servers in dozens of domains, so I need some way to pass along credentials.
Here's the meat of my script:
$server = "<computername>"
$schedule = new-object -com("Schedule.Service")
$Schedule.connect($server)
$folder = $schedule.GetFolder("")
$tasks = $folder.GetTasks("")
foreach($task in $tasks) {
if (($task = $Folder.GetTasks(0))) {
$Tasks| ForEach-Object {[array]$results += $_}
$Tasks | Foreach-Object {
New-Object -TypeName PSCustomObject -Property #{
'Name' = $_.name
<etc.>
<etc.>
}
}
}
That code works fine either on my localhost or a server in the same domain as my workstation. In other scripts, I use Get-Credential to create $creds and (in various ways) pass that to the appropriate cmdlet. But with this one, I'm not sure. 'New-Object' doesn't accept a -Credential parameter. I've tried wrapping various parts inside an Invoke-Command scriptblock, since that accepts -Credential, but it fails in various ways. I'm not sure what needs to be wrapped in Invoke-Command--just the new-object? The foreach loop? The entire thing?
Thanks in advance.
When doing the Connect call, you can pass the server, domain, username, and password:
$Schedule.Connect($serverName, $user, $domain, $password);
This should allow you to use that object on the new domain.
MSDN Reference

COMAdmin - force refresh of applications after install of proxy

I'm programmatically installing a COM+ proxy component via Powershell, using msiexec on the msi, and then using the COMAdmin.COMAdminCatalog object to set the remote server on the proxy.
The problem is that it takes a while for the newly installed proxy to be available in the "Applications" collection of COMAdminCatalog. Is there some way to force a refresh of the catalog before getting the application list?
Essentially, what I do is this:
msiexec /q /i $appName.msi
use the COMAdmin.COMAdminCatalog to enumerate the apps.
function Set-Remote-Server-For-Complus-Application($appName, $remoteServer) {
$comAdmin = New-Object -comobject COMAdmin.COMAdminCatalog
$apps = $comAdmin.GetCollection("Applications")
$apps.Populate();
$app = $apps | Where-Object {$_.Name -eq $appName}
if ($app -eq $null) {
Write-Warning "Unable to find COM+ app ""$appName""."
Return
}
$app.Value("ApplicationProxyServerName") = $remoteServer
$result = $apps.SaveChanges()
$apps = $null
if ($result -eq 1) {
Write-Output "Successfully set complus remote server ""$remoteServer"" on ""$appName"""
}
}
The problem is that the application is not Found. If I add a Start-Sleep -Seconds 2 between the calls, it works. But, sleeping is not good, because sometimes it might take longer than 2 seconds, sometimes it might only take 200 milliseconds, so the wait is unnecessarily long.
Is there any way to make sure that the COMAdmin.COMAdminCatalog is actually updated before I try to enuerate the applications, without resorting to sleeping and just hoping for the best?