Provider cannot be found when try to open/access mdb - powershell

I'm writing a powershell 5.1 script to query info from a mdb file based on this article. I get this error message when I try to open/access an mdb file:
MDB Open next
Provider cannot be found. It may not be properly installed.
I'm pretty sure I need to adjust my connection info according to what I have installed. This is what I'm doing:
$pathViewBase = 'C:\Data\EndToEnd_view\' #View dir.
$XML_MDB_Dirs = #('\AppText.mdb') #more files later
foreach($mdbFile in $XML_MDB_Dirs)
{
$pathToMdb = Join-Path -Path $pathViewBase -ChildPath $mdbFile
if(Test-Path $pathToMdb)
{
$cn = new-object -comobject ADODB.Connection
$rs = new-object -comobject ADODB.Recordset
Write-Host "MDB Open next" -ForegroundColor DarkCyan
$cn.Open("Provider = Microsoft.Jet.OLEDB.4.0;Data Source = $pathToMdb") ###error this line
Write-Host "Open done" -ForegroundColor DarkCyan
$rs.Open(“SELECT TOP 1 [TableName].[Message Description],
[TableName].[Column1]
FROM [TableName]
WHERE [TableName].[Message Description] = 'ERROR'”,
$cn, $adOpenStatic, $adLockOptimistic)
$rs.MoveFirst()
Write-Host "Message value obtained for ERROR: " $rs.Fields.Item("Name").Value
Break ##########################
}#test-Path
}#foreach
I found this regarding odbc connections, and it seems to say I need to adjust my connection info. Looking at what's installed on my computer, I see this, but I'm a little unclear what I need to adjust my open code to use. Would I need to replace 'Microsoft.Jet.OLEDB.4.0' with 'SQLNCLI11.dll'?
Update:
I checked,
(Get-WmiObject Win32_OperatingSystem).OSArchitecture
and I am running 64 bit powershell, so since I installed accessdatabaseengine_x64.exe access database engine, per #
Mathias R. Jessen below (and rebooted), that's correct. But I still get the same error. I'm not sure if there's something I could check to see if it's installed correctly, or if I need to use SQLNCLI11.0 as the provider instead of Microsoft.Jet.OLEDB.4.0, or if I need to add "using" at the top? Or do I need to check if a powershell module is installed?

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

Sharepoint online - MoveFile - pnp.powershell Status Updates

I'm trying to do folder/files moves from one sharepoint site to another, and I can't seem to get the Receive-PnPCopyMoveJobStatus to work in my powershell script
Right now the only way I can monitor a file/folder move is to monitor the source's recycling bin for changes. I'd like to be able to get progress either on demand, or consistently in an open powershell. Ideally I'd like to see a percentage sign, and even a verbose option.
Here's what I have put together:
#Config Variables
$SiteURL = "https://<site>.sharepoint.com/
$SourceFolderURL= "sites/<site name>/<document library name>/<Folder or file location>"
$TargetFolderURL = "sites/<site name>/<document library name>"
#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -interactive
#Sharepoint Copy/Move operation feedback
$Test = "Move-PnPFile -SourceUrl $SourceFolderURL -TargetUrl $TargetFolderURL -Overwrite -noWait"
$jobStatus = "Receive-PnPCopyMoveJobStatus -Job $Test"
if($jobStatus.JobState -eq 0)
{
Write-Host "Job finished"
}
referencing:
https://learn.microsoft.com/en-us/powershell/module/sharepoint-pnp/receive-pnpcopymovejobstatus?view=sharepoint-ps
I haven't been successful in running this. When I fill in the site names, library names, and actual site, I get a result that looks like it completes, but with no feedback, nor do the files move. So essentially nothing happens.
What does work for the file/folder move is the following:
#Config Variables
$SiteURL = "https://<site>.sharepoint.com/"
$SourceFolderURL= "sites/<site name>/<document library>/<folder name>"
$TargetFolderURL = "sites/<site name>/<document library>"
#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -interactive
#sharepoint online powershell move folder
Move-PnPFile -SourceUrl $SourceFolderURL -TargetUrl $TargetFolderURL -overwrite
#Read more: https://www.sharepointdiary.com/2017/06/how-to-move-folder-in-sharepoint-online.html#ixzz7Bkp822M1
Any help on correcting this script, or other methods on seeing the progress of Copy or Move operations on SharePoint would be appreciated!
The source url should be like "<document library>/<file name>"
Please try following script
$SiteURL = "https://<site>.sharepoint.com/sites/<sitesname>
$SourceFolderURL= "<document library name>/<file name>"
$TargetFolderURL = "<document library name>/<target file name>"
$job = Move-PnPFile -SiteRelativeUrl $SourceFolderURL -TargetUrl $TargetFolderURL -Overwrite
$jobStatus = Receive-PnPCopyMoveJobStatus -Job $result
if($jobStatus.JobState == 0)
{
Write-Host "Job finished"
}
Your non-working script contains:
$Test = "Move-PnPFile -SourceUrl $SourceFolderURL -TargetUrl $TargetFolderURL -Overwrite -noWait"
$jobStatus = "Receive-PnPCopyMoveJobStatus -Job $Test"
Both of these variable values are strings. They don't do anything except exist, and do not cause any commands to run. $jobStatus.JobState will always be null and never zero, because JobState is not a property of a string, so the if condition is never met.
If you want to run the commands, don't write them as strings inside double quotes, but just as they are in the documentation you referred to. You can actually run them, and capture their output, with e.g.
$jobStatus = Receive-PnPCopyMoveJobStatus -Job $Test
You can also just copy and paste the example and update the parameter values (though it seems to have the wrong variable name on the second line, which you've already fixed). You may have further errors once the commands are running, which should provide further diagnostic information. Make sure that you are doing all of connecting, requesting the move, and retrieving the status information in the same script.

Read encrypted connection string in Machine.config from Powershell

Is it possible to read the encrypted connection string in Machine.config from Powershell script?
Due to security reason, we are trying to move the hardcoded connection string from PowerShell script to Machine.config
Update: Powershell script is supposed to read the connection string from Machine.config (Encrypted through aspnet_regiis) and connect to the DB.
I'm not sure where PowerShell figures into your question. If you use a built-in command like aspnet_regiis.exe to encrypt a configuration section, then your IIS site is unaware that the section is encrypted.
I'm not sure how putting something in machine.config is going to make an app more secure since anything that reads it transparently would work for any app on that machine.
The way .net configs work is you have an some.exe and it has a some.exe.config file. When you deploy some.exe you can (should?) include a step to encrypt sensitive sections. The app would still just read the data, unaware that it's been encrypted.
But again that is the app, not powershell that's reading the encrypted value.
Here's a section of a script I use that encrypts/decrypts sections. Use carefully since data encrypted can only be decrypted on the same machine (and likely the same OS). YMMV
$appConfig = "your.exe"
$sectionName = "appSettings"
$dataProtectionProvider = "DataProtectionConfigurationProvider"
if (-not (Test-Path $path) ) { throw "Unable to find $($appConfig) $($path)" }
$configuration = [System.Configuration.ConfigurationManager]::OpenExeConfiguration($path)
$section = $configuration.GetSection($sectionName)
if (-not $section.SectionInformation.IsProtected) {
$section.SectionInformation.ProtectSection($dataProtectionProvider)
$section.SectionInformation.ForceSave = $true
$configuration.Save([System.Configuration.ConfigurationSaveMode]::Full)
Write-Information -Message "$($sectionName) in $($appConfig) has been protected from casual users"
}
else {
Write-Information -Message "$($sectionName) in $($appConfig) is already protected"
$section.SectionInformation.UnprotectSection()
$section.SectionInformation.ForceSave = $true
$configuration.Save([System.Configuration.ConfigurationSaveMode]::Full)
Write-Information -Message "$($sectionName) in $($appConfig) protection removed"
}
This is a snippet of a full script to encrypt/decrypt config sections.
The previous answer was largely correct, I did have to make a couple minor changes to get it working on my system with respects to the 'path' and 'appConfig' variables. For this script to work I am placing the powershell script in the same folder as the exe and config file I'm working with.
#This script will encrypt/decrypt the section specified in the sectionName variable of a .net configuration file
#using the DataProtectionConfigurationProvider method of encryption/decryption.
#Place this file in the same folder as the executable/config file and run it, be sure to update the 'appConfig'
#and 'sectionName' variables accordingly.
$path = Get-Location
$appConfig = "ServionDataRecovery.exe"
$sectionName = "connectionStrings"
$dataProtectionProvider = "DataProtectionConfigurationProvider"
if (-not (Test-Path $appConfig) ) { throw "Unable to find $($appConfig) $($path)" }
$configuration = [System.Configuration.ConfigurationManager]::OpenExeConfiguration("$path\$appConfig")
$section = $configuration.GetSection($sectionName)
if (-not $section.SectionInformation.IsProtected) {
$section.SectionInformation.ProtectSection($dataProtectionProvider)
$section.SectionInformation.ForceSave = $true
$configuration.Save([System.Configuration.ConfigurationSaveMode]::Full)
Write-Host "$($sectionName) in $($appConfig) has been protected from casual users"
}
else {
Write-Host "$($sectionName) in $($appConfig) is already protected"
$section.SectionInformation.UnprotectSection()
$section.SectionInformation.ForceSave = $true
$configuration.Save([System.Configuration.ConfigurationSaveMode]::Full)
Write-Host "$($sectionName) in $($appConfig) protection removed"
}

How to run Powershell script on local computer but with credentials of a domain user

I have to implement a solution where I have to deploy a SSIS project (xy.ispac) from one machine to another. So far I've managed to copy-cut-paste the following stuff from all around the internet:
# Variables
$ServerName = "target"
$SSISCatalog = "SSISDB" # sort of constant
$CatalogPwd = "catalog_password"
$ProjectFilePath = "D:\Projects_to_depoly\Project_1.ispac"
$ProjectName = "Project_name"
$FolderName = "Data_collector"
# Load the IntegrationServices Assembly
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Management.IntegrationServices")
# Store the IntegrationServices Assembly namespace to avoid typing it every time
$ISNamespace = "Microsoft.SqlServer.Management.IntegrationServices"
Write-Host "Connecting to server ..."
# Create a connection to the server
$sqlConnectionString = "Data Source=$ServerName;Initial Catalog=master;Integrated Security=SSPI;"
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection $sqlConnectionString
$integrationServices = New-Object "$ISNamespace.IntegrationServices" $sqlConnection
$catalog = $integrationServices.Catalogs[$SSISCatalog]
# Create the Integration Services object if it does not exist
if (!$catalog) {
# Provision a new SSIS Catalog
Write-Host "Creating SSIS Catalog ..."
$catalog = New-Object "$ISNamespace.Catalog" ($integrationServices, $SSISCatalog, $CatalogPwd)
$catalog.Create()
}
$folder = $catalog.Folders[$FolderName]
if (!$folder)
{
#Create a folder in SSISDB
Write-Host "Creating Folder ..."
$folder = New-Object "$ISNamespace.CatalogFolder" ($catalog, $FolderName, $FolderName)
$folder.Create()
}
# Read the project file, and deploy it to the folder
Write-Host "Deploying Project ..."
[byte[]] $projectFile = [System.IO.File]::ReadAllBytes($ProjectFilePath)
$folder.DeployProject($ProjectName, $projectFile)
This seemed to be working surprisingly well on the development machine - test server pair. However, the live environment will be a bit different, the machine doing the deployment job (deployment server, or DS from now on) and the SQL Server (DB for short) the project is to be deployed are in different domains and since SSIS requires windows authentication, I'm going to need to run the above code locally on DS but using credentials of a user on the DB.
And that's the point where I fail. The only thing that worked is to start the Powershell command line interface using runas /netonly /user:thatdomain\anuserthere powershell, enter the password, and paste the script unaltered into it. Alas, this is not an option, since there's no way to pass the password to runas (at least once with /savecred) and user interactivity is not possible anyway (the whole thing has to be automated).
I've tried the following:
Simply unning the script on DS, the line $sqlConnection = New-Object System.Data.SqlClient.SqlConnection $sqlConnectionString would use the credentials from DS which is not recognized by DB, and New-Object does not have a -Credential arg that I could pass to
Putting everything into an Invoke-Command with -Credential requires using -Computername as well. I guess it would be possible to use the local as 'remote' (using . as Computername) but it still complains about access being denied. I'm scanning through about_Remote_Troubleshooting, so far without any success.
Any hints on how to overcome this issue?
A solution might be to use a sql user (with the right access rights) instead of an AD used.
Something like this should work.
(Check also the answer to correct the connection string)

Dynamic AppLocker policies applied with powershell at startup, doesn't work until after two minutes

We have an issue with dynamic creation of applocker rules at startup. We are using local GPO on windows 7. Domain GPO is not an option in the project.
In our case we use a powershellscript to import applocker rules at system startup.
The problem is that the rules doesn't take effect before the system has been live for approximately 2 minutes. After that, we can lock/unlock as we want to on the fly.
I have checked that the AppIDSvc service is set to autostart, and I can see that it is running. I have also checked the services it depends on. They autostart too (not auto delayed)
I don't see any errors in eventlog.
Can anyone tell me if there is a command to use to force an update? I have tried the gpudate without any luck... Have also tried to restart the applocker service.
Hope to hear from someone soon.
Here is a code sample to lock down calculator for the local user "abc" - just as an example.
Lock:
Import-Module AppLocker
$id = [guid]::NewGuid()
$tmpFileName = "c:\temp\temp.xml"
$appPath = "C:\Windows\system32\calc.exe"
$identity = "abc"
$objUser = New-Object System.Security.Principal.NTAccount($identity)
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$identitySid = $strSID.Value
"<AppLockerPolicy Version=""1"">
<RuleCollection Type=""Exe"" EnforcementMode=""Enabled"">
<FilePathRule Id=""$id"" Name=""temp-$appPath"" Description=""Denies access to $appPath"" UserOrGroupSid=""$identitySid"" Action=""Deny"">
<Conditions>
<FilePathCondition Path=""$appPath"" />
</Conditions>
</FilePathRule>
</RuleCollection>
</AppLockerPolicy>" | out-file $tmpFileName
Set-AppLockerPolicy -XMLPolicy $tmpFileName -Merge
Remove-Item $tmpFileName
Unlock:
Import-Module AppLocker
$tmpFileName = "c:\temp\temp.xml"
$appPath = "C:\Windows\system32\calc.exe"
[xml]$ruleXml = Get-AppLockerPolicy -Local -XML
$ruleNode = $ruleXml.SelectSingleNode("//FilePathRule[#Name='temp-$appPath']")
if ($ruleNode -ne $null)
{
[void]$ruleNode.ParentNode.RemoveChild($ruleNode)
$ruleXml.Save($tmpFileName)
Set-AppLockerPolicy -XMLPolicy $tmpFileName
Remove-Item $tmpFileName
}
Kind regards,
Morten