I have a large number of PDF files in a folder with several subfolders. In this pile of files I need to find the ones with a specific string and move them to a new destination.
I already have a fine piece of code for the search process that gives me the files needed (thx to the creator) - now I need help to combine this code with a move-function. All the files found by the following code should be moved to a new destination.
$searchString = "text i need to find"
$searchPath = "C:\test"
$sql = "SELECT System.ItemPathDisplay, System.DateModified, "
+ "System.Size, System.FileExtension FROM SYSTEMINDEX "
+ "WHERE SCOPE = '$searchPath' AND FREETEXT('$searchstring')"
$provider = "provider=search.collatordso;extended properties=’application=windows’;"
$connector = new-object system.data.oledb.oledbdataadapter -argument $sql, $provider
$dataset = new-object system.data.dataset
if ($connector.fill($dataset)) { $dataset.tables[0] }
The output is like:
SYSTEM.ITEMPATHDISPLAY SYSTEM.DATEMODIFIED SYSTEM.SIZE SYSTEM.FILEEXTENSION
---------------------- ------------------- ----------- --------------------
C:\test\file.pdf 27.08.2019 19:14:57 17119 .pdf
Thank you for your help!
I found a solution by myself. For anyone interested.
Note: $searchPath must be a local drive on the machine you are running the script on, because the PDF files need to be indexed by the windows search. For that you probably have to install an iFilter: https://superuser.com/questions/402673/how-to-search-inside-pdfs-with-windows-search
$searchString = "Merkblatt für nüchtern eintretende Patienten"
$searchPath = "Y:\"
$targetPath = "\\Server\Path\folder"
$sql = "SELECT System.ItemPathDisplay, System.DateModified, " +
"System.Size, System.FileExtension FROM SYSTEMINDEX " +
"WHERE SCOPE = '$searchPath' AND FREETEXT('$searchstring')"
$provider = "provider=search.collatordso;extended properties=’application=windows’;"
$connector = new-object system.data.oledb.oledbdataadapter -argument $sql, $provider
$dataset = new-object system.data.dataset
if ($connector.fill($dataset)) {
#$dataset.tables[0]
foreach ( $Row in $dataset.tables[0].Rows) {
$targetFile = $Row[0] -replace "^Y:", $targetPath
$targetSubfolder = Split-Path -Path $targetFile
#write-host "Targetfile : $targetFile"
#write-host "Moving: $($Row[0])"
Move-Item -Path $($Row[0]) -Destination $targetPath -Force
}
}
Related
I am trying to convert .pptx file to .pdf using powershell. I have used below code
write-host "Converting pptx to pdf....." -ForegroundColor Green
$ppt = New-Object -com powerpoint.application
$opt = [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType]::ppSaveAsPDF
$ifile = $file.FullName
$pres = $ppt.Presentations.Open($ifile)
$pathname = split-path $ifile $filename = Split-Path $ifile -Leaf
$file = $filename.split(".")[0]
$ofile = $pathname + "\" + $file + ".pdf"
$pres.SaveAs($ofile, $opt)
While running the code, i am getting error as:
Error HRESULT E_FAIL has been returned from a call to a COM component.
Any help would be highly appreciated
$pptx = "C:\test\test.pptx"
$pdf = "C:\test\test.pdf"
$ppt = New-Object -ComObject PowerPoint.Application
$ppt.Visible = $True
$presentation = $ppt.Presentations.Open($pptx)
$presentation.SaveAs($pdf, [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType]::ppSaveAsPDF)
$presentation.Close()
$ppt.Quit()
I'm trying to achieve the following via powershell:
I have a table(TBL_DDL) with 5 columns (CATALOG,SCHEMA,OBJECT_TYPE,OBJECT_NAME,DDL)
Now, i'm extract data from this table and then trying to create a folder structure by concatenating first 4 columns (CATALOG,SCHEMA,OBJECT_TYPE,OBJECT_NAME) in C: drive and then exporting the data in DDL column in txt file.
For eg: C:\"CATALOG"\"SCHEMA"\"OBJECT_TYPE"\"OBJECT_NAME"\DDL.txt
I'm trying to achieve this via powershell. Can anyone help me please?
$SqlCmd = 'snowsql -c example -d tu_test -s public -q "select catalog,schema,OBJECT_TYPE,OBJECT_NAME,DDL from SF_TBL_DDL limit 2"'
$MultiArray = #(Invoke-Expression $SqlCmd)
$dt = New-Object System.Data.Datatable
[void]$dt.Columns.Add("CATALOG")
[void]$dt.Columns.Add("SCHEMA")
$Output = foreach ($Object in $MultiArray)
{
foreach ($SCHEMA in $Object.SCHEMA)
{
$someother = New-Object -TypeName psobject -Property #{CATALOG = $Object.CATALOG; SCHEMA = $SCHEMA}
$nRow = $dt.NewRow()
$nRow.CATALOG = $someother.CATALOG
$nRow.SCHEMA = $someother.SCHEMA
$dt.Rows.Add($nRow)
}
}
$dt.row.count
At the moment, i'm getting 0 rows in $dt.
Cheers
You can use System.Data.DataTable object the pull your result set and then loop through it to perform the required operation.
Here GetTableValues function will retrieve the table values and then use following cmdlet to create directory and file
New-Item -ItemType "directory" -Path $dirPath
New-Item -ItemType "file" -Path $filePath
Complete code looks like this
function GetTableValues(){
$DBConnectionString = "<Your DB connection string>";
$sqlConn = new-object System.Data.SqlClient.sqlConnection $DBConnectionString;
$sqlConn.Open();
$sqlCommand = $sqlConn.CreateCommand();
$sqlCommand.CommandText = "select catalog,[schema],OBJECT_TYPE,OBJECT_NAME,DDL from TBL_DDL"; ##Put your correct query here
$result = $sqlCommand.ExecuteReader();
$table = New-Object System.Data.DataTable;
$table.Load($result);
$sqlConn.Close();
return $table;
}
$tableValue = GetTableValues;
foreach ($Row in $tableValue)
{
$filePath = "C:\" + $Row.catalog.TrimEnd() + "\" + $Row.schema.TrimEnd() + "\" + $Row.OBJECT_TYPE.TrimEnd() + "\" + $Row.OBJECT_NAME.TrimEnd() + "\" + $Row.DDL.TrimEnd() + ".txt"
$dirPath = "C:\" + $Row.catalog.TrimEnd() + "\" + $Row.schema.TrimEnd() + "\" + $Row.OBJECT_TYPE.TrimEnd() + "\" + $Row.OBJECT_NAME.TrimEnd()
New-Item -ItemType "directory" -Path $dirPath ##Creates directory
New-Item -ItemType "file" -Path $filePath ##Creates file in $dirPath directory
}
This works perfectly fine for me.
I want to get the author(who created) a folder in a Sharepoint Online using PnP PowerShell. The time last modified I can get it, but the field author I cannot get it. I know that can be two different fields, author and modifier, but I cannot get any from this.
For the folders:
$folder = Get-PnPFolderItem -FolderSiteRelativeUrl $folderPath -ItemName $subfolderName
Write-Host "URL : " $folder.ServerRelativeUrl
Write-Host "Name : " $folder.Name
Write-Host "Modified : " $folder.TimeLastModified
# above are ok, but $folder has no author property
# same next line fails, Author it does not exist
$folder= Get-PnPFolder -Url "$folderPath/$subfolderName" -Includes ListItemAllFields.Author
For the files, is easy I use:
Get-PnPFile -ServerRelativeUrl $file.ServerRelativeUrl -Path $destinationfolder -FileName $file.Name -AsFile
$f = Get-PnPFile -Url "$($folderUrl)/$($file.Name)" -AsListItem
$fileDetails = #{
File = "$($destinationFolder)/$($file.Name)"
Author = $f["Author"].Email
Created = $f["Created"]
}
I just find the solution, if anyone need:
context = Get-PnPContext
$context.load($context.Web)
$context.ExecuteQuery()
$list = $context.Web.Lists.GetByTitle("Documente")
$context.Load($list)
$context.ExecuteQuery()
$camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery
$camlQuery.ViewXml ="<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='FileRef' /><Value Type='Text'>/server/folder/relativepath</Value></Eq></Where></Query></View>";
$allItems=$list.GetItems($camlQuery)
$context.Load($allItems)
$context.ExecuteQuery()
foreach($item in $allItems){
Write-Host "##############"
Write-Host $item["FileRef"]
$item["Author"].Email
$item["Modified"]
}
How do I reference a specific email address in this code it always directs to
the default email account. I have multiple email accounts in my outlook and I want to download emails from a different account which I want to reference by that email address . I have a feeling
$folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)
has to be changed please give suggestions.
`[CmdletBinding(DefaultParameterSetName="All")] `
`Param(
[Parameter(Mandatory=$true,
Position=0,
HelpMessage='Folder path to store emails. Do not use quotation marks even if the path has spaces.',
ValueFromPipelineByPropertyName=$true
)]
[Alias("Destination", "Dest", "FullName")]
[String]$DestinationPath, `
[Parameter(ParameterSetName="All")]
[Parameter(Mandatory=$true,ParameterSetName="Unread")]
[Switch]$UnreadOnly,
[Parameter(ParameterSetName="Unread")]
[Switch]$MarkRead
)
#Removes invalid Characters for file names from a string input and outputs
the clean string
` #Similar to VBA CleanString() Method
#Currently set to replace all illegal characters with a hyphen (-)
Function Remove-InvalidFileNameChars {`
param(
[Parameter(Mandatory=$true, Position=0)]
[String]$Name
)
return [RegEx]::Replace($Name, "[{0}]" -f ([RegEx]::Escape([String][System.IO.Path]::GetInvalidFileNameChars())), '-')
}
#Test for destination folder nonexistence
if (!(Test-Path $DestinationPath)) {
#Set values for prompt and menu
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
"Confirmation Choice"
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
"Negative Response"
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$title = "Invalid Destination"
$message = "The folder you entered does not exist. Would you like to create the folder?"
#Prompt for folder creation and store answer
$result = $host.UI.PromptForChoice($title, $message, $options, 0)
#If yes, create.
if ($result -eq 0) {
New-Item $DestinationPath -ItemType Directory | Out-Null
Write-Host "Directory created."
}
#If no, exit
else {exit}
}
#Add a trailing "\" to the destination path if it doesn't already
if ($DestinationPath[-1] -ne "\") {
$DestinationPath += "\"
}
#Add Interop Assembly
Add-type -AssemblyName "Microsoft.Office.Interop.Outlook" | Out-Null
#Type declaration for Outlook Enumerations, Thank you Hey, Scripting Guy! blog for this demonstration
$olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$olSaveType = "Microsoft.Office.Interop.Outlook.OlSaveAsType" -as [type]
$olClass = "Microsoft.Office.Interop.Outlook.OlObjectClass" -as [type]
#Add Outlook Com Object, MAPI namespace, and set folder to the Inbox
$outlook = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNameSpace("MAPI")
#Future Functionality to Receive Email before saving - Still Needs Testing
#$outlook.Session | Out-Null
#$outlook.Session.SendAndReceive($false) | Out-Null
$folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)
#Iterate through each object in the chosen folder
foreach ($email in $folder.Items) {
#Get email's subject and date
[string]$subject = $email.Subject
[string]$sentOn = $email.SentOn
#Strip subject and date of illegal characters, add .msg extension, and combine
$fileName = Remove-InvalidFileNameChars -Name ($sentOn + "-" + $subject + ".msg")
#Combine destination path with stripped file name
$dest = $DestinationPath + $fileName
#Test if object is a MailItem
if ($email.Class -eq $olClass::olMail) {
#Test if UnreadOnly switch was used
if ($UnreadOnly) {
#Test if email is unread and save if true
if ($email.Unread) {
#Test if MarkRead switch was used and mark read
if ($MarkRead) {
$email.Unread = $false
}
$email.SaveAs($dest, $olSaveType::olMSG)
}
}
#UnreadOnly switch not used, save all
else {
$email.SaveAs($dest, $olSaveType::olMSG)
}
}
}
Think You can do something like this:
$outlook = New-Object -ComObject Outlook.Application
$namespace =$outlook.GetNameSpace("MAPI")
$namespace.Logon("Profilename","profilepassword",$false,$false)
Also you can use Assembly - Microsoft.Exchange.WebServices.dll and do something like this:
[Reflection.Assembly]::LoadFile("C:\Program Files (x86)\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll") > $nul
$getref = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2)
$getref.Credentials = New-Object Net.NetworkCredential('Account', 'Password', 'domain.local')
$getref.AutodiscoverUrl("Account#domain.com")
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($getref,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
#Write-Host "Total Messages:" $inbox.TotalCount
$psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView($inbox.TotalCount)
$fiItems = $getref.FindItems($Inbox.Id,$ivItemView)
[Void]$getref.LoadPropertiesForItems($fiItems,$psPropset)
foreach($Item in $fiItems.Items){
if ($Item.From -EQ "Somemail#domain.com") {
New-Object -TypeName PSObject -Property #{
Emails = $Item.From
} | select Emails
}
}
Hello! You can load a body text (to html) something like this:
foreach($Item in $fiItems.Items){
if ($Item.Subject -match "Something special") {
$Item.Load()
$Save = ((Get-Date -Format "yyMMdd") + "-" + $Item.Subject[0] + ".html")
New-Item -Path "C:\file\exch\" -name $Save -ItemType file -value $Item.Body.Text
}
}
I m trying to copy documents from list in one sharepoint to another :
this is my code :
*************************************************
$source= "\\...\s1"
$destination = "\\..\s2"
foreach ($result in $result )
{ copy-item -path $source -dest $destination}
*************************************************
-$result is the list of all documents that I got using web-services, it s type is system.array
-$source and $destination are UNC that refers to URL of the two sharepoint
the error is
" can not find the path \...\s1system.xml.Xml.XmlElement"
PS: I m not using server machine,it s just a client
Here is my code
*****************************************************
{
param (
[String]$Value,
[String]$Field,
[String]$RowLimit = "0",
[String]$Operator = "Contains",
[String]$WebURL = "https://.................../wer",
[String]$ListName = "Main documents",
[String]$ViewName,
[Switch]$Recurse
)
$ScriptDirectory = split-path $MyInvocation.MyCommand.Definition
$dllPath = "P:\SamlCookieAuth.dll" -f $ScriptDirectory
[void][System.Reflection.Assembly]::LoadFrom($dllPath)
$queryOptionsValue = ''
if ($Recurse)
{
$queryOptionsValue = '<ViewAttributes Scope="RecursiveAll"/>'
}
$WSUri = $WebURL + "/_vti_bin/Lists.asmx?wsdl"
$listsWebServiceReference = New-WebServiceProxy -Uri $WSUri -UseDefaultCredential
$listsWebServiceReference.Url = $webURL + "/_vti_bin/lists.asmx"
[System.Uri]$CookieUri = $WebURL
$listsWebServiceReference.CookieContainer = [ST.SamlCookieAuth.SamlCookieManager]::GetAuthenticatedCookiesContainer($CookieUri.AbsoluteUri, 0, 0)
[System.Xml.XmlDocument]$xmlDoc = New-Object -TypeName System.Xml.XmlDocument
[System.Xml.XmlElement]$queryOptions =$xmlDoc.CreateElement("QueryOptions")
$queryOptions.InnerXml = $queryOptionsValue
if ($PSBoundParameters.Keys.Contains("Value"))
{
[System.Xml.XmlElement]$query = $xmlDoc.CreateElement("Query")
$queryValue = "<Where><$Operator><FieldRef Name='$Field'/><Value Type='Text'>$Value</Value></$Operator></Where>"
$query.InnerXml = $queryValue
$result=$listsWebServiceReference.GetListItems($listName, $viewName, $query, $null, $rowLimit, $queryOptions, $null).data.row
}
else
{
$result=$listsWebServiceReference.GetListItems($listName, $viewName, $null, $null, $rowLimit, $queryOptions, $null).data.row
}
$destDirectory = "\\.............\TER\Main Documents"
foreach ($resul in $result)
{Copy-Item -path $resul -destination $destDirectory }
}
Perhaps the problem that you are having is the result of a conversion issue. You are trying to write content from one SP to another as a document, however, you cannot do so with an XmlElement.
Suggest checking out this post:
Converting system.xml.xmlelement to system.xml.xmldocument with PowerShell
It would be helpful to see the content of "-$result is the list of all documents that I got using web-services, it s type is system.array".
Also, for readability, I would suggest differentiating between $result and $result as follows:
foreach($document in $documentList){}
-or- (at minimum)
foreach($result in $results){}