I have a script which I think is most of the way to being able to grab IE history for all of the users on a machine. My problem is it doesn't work for users other than myself because I get a permissions error when attempting open the folder. Does anyone have any ideas how I can fix the permissions problem?
I'm running this script on a Windows 2012r2 machine and I am an administrator on the box.
Thanks!
function Get-History
{
param
(
[string]$userName
)
$shell = New-Object -ComObject Shell.Application
if($username)
{
$users = $username
}
else
{
$users = Get-ChildItem C:\Users
}
if((([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")))
{
Foreach($user in $users)
{
$user = Split-Path $user -leaf
try
{
$ErrorActionPreference = 'Stop'
$hist = $shell.NameSpace("C:\Users\$user\AppData\Local\Microsoft\Windows\History")
}
catch
{
continue
}
$folder = $hist.Self
#$folder.Path
if($hist){
$hist.Items() | foreach {
#""; ""; $_.Name
if ($_.IsFolder) {
$siteFolder = $_.GetFolder
$siteFolder.Items() | foreach {
$site = $_
#""; $site.Name
if ($site.IsFolder) {
$pageFolder = $site.GetFolder
$pageFolder.Items() | foreach {
$url = $pageFolder.GetDetailsOf($_,0)
$date = $pageFolder.GetDetailsOf($_,2)
#"$user`: $date visited $url"
#Write-Output ("$user,$date,`"$url`"" | ConvertFrom-Csv)
New-Object -TypeName PSObject -Property #{
user=$user;
date = $date;
url = $url
}
}
}
}
}
}
}
}
}
else
{
Write-Host "Not Admin"
}
}
If I run just the small snippet:
$shell = New-Object -ComObject Shell.Application
$hist = $shell.NameSpace("C:\Users\MyOwnUsername\AppData\Local\Microsoft\Windows\History")
Then I successfully assign the $hist variable as a System.__ComObject
But if I run:
$shell = New-Object -ComObject Shell.Application
$hist = $shell.NameSpace("C:\Users\SomeOtherUser\AppData\Local\Microsoft\Windows\History")
I get:
Exception calling "NameSpace" with "1" argument(s): "Unspecified error (Exception from HRESULT: 0x80004005 (E_FAIL))"
At line:3 char:1
+ $hist = $shell.NameSpace("C:\Users\SomeOtherUser\AppData\Local\Microsoft\Windows\History ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
Full Disclosure: it's a slight modification of the script at this blog post
I never solved the permissions problem. I changed strategy to use BrowsingHistoryViewer by Nirsoft.
$execPath = "C:\BrowsingHistoryView.exe"
$computers = 'computer1','computer2','computer3','computer4'
$outPath = "c:\"
$computers |
ForEach-Object{ `
Start-Process $execPath `
-argumentList "/HistorySource 3",
"/HistorySourceFolder ""\\$_\c$\Users""",
"/scomma ""$outpath\history_$_.txt"""
}
Related
I have this PowerShell code.
Works good. But when I add more lines to db.csv, it doesn't work and return error code:
Exception calling "Open" with "1" argument(s): "Connection has been unexpectedly closed. Server sent command exit status 0.
Authentication log (see session log for details):
Using username "username".
Authentication failed."
At C:\Users\me\Desktop\testeScript\CollectLog.ps1:41 char:5
+ $session.Open($sessionOptions)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SessionRemoteException
When I have for example only two lines in db.csv the script works very well
HostName,IP
name1,10.10.1.1
name2,10.10.1.2
I try with 19 hostname and Ip addr line in CSV doc and works, but when I add only 1 more stopping works.
19 works
20+ doesn't work..
Any idea? (Thank you and sorry for my english)
Add-Type -Path "WinSCPnet.dll"
$Name = #()
$ip = #()
Import-Csv db.csv |`
ForEach-Object {
$Name += $_.HostName
$ip += $_.IP
}
$inputID = Read-Host -Prompt "Type ID"
if ($Name -contains $inputID)
{
$Where = [array]::IndexOf($Name, $inputID)
Write-Host "IP: " $ip[$Where]
}
# Set up session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Sftp
HostName = "$ip"
UserName = "username"
Password = "password"
GiveUpSecurityAndAcceptAnySshHostKey = "true"
}
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Transfer files
$session.GetFiles("/C:/Program Files/Common Files/logs/Device.log", "E:\loguri\Log\Arhive\*").Check()
}
finally
{
$session.Dispose()
}
Compress-Archive -Path "E:\loguri\Log\Arhive\Device.log" -DestinationPath "E:\loguri\Log\Arhive\$inputID.zip" -Update
Remove-Item -Path "E:\loguri\Log\Arhive\Device.log" -Force
as Theo says you have no need to separate out your CSV into two arrays as you have. Import it like this
$db = import-csv 'db.csv'
You can access each row as $db[0], $db[1] and each column from your CSV will be a property, e.g. $db[0].Hostname and $db[0].IP
After you have read in your input you just need to select the entry from the array $db. Perhaps like this. However neither your code nor mine covers the case where is no match!
$entry = $db -match $inputID
Then your session will be defined like this
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Scp
HostName = $entry.ip
UserName = "username"
Password = "password"
GiveUpSecurityAndAcceptAnySshHostKey = "true"
}
With all that said, given the error message that you have it would appear that the combination of username/password and ip are not valid.
Add-Type -Path "WinSCPnet.dll"
$db = import-csv 'db.csv'
$inputID = Read-Host -Prompt "Type ID"
$entry = $db -match $inputID
# Set up session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Sftp
HostName = $entry.IP
UserName = "username"
Password = "password"
GiveUpSecurityAndAcceptAnySshHostKey = "true"
}
$session = New-Object WinSCP.Session
try {
# Connect
$session.Open($sessionOptions)
# Transfer files
$session.GetFiles("/C:/Program Files/Common Files/logs/Device.log", "E:\loguri\Log\Arhive\*").Check()
}
finally {
$session.Dispose()
}
if (Test-Path "E:\loguri\Log\Arhive\Device.log") {
Compress-Archive -Path "E:\loguri\Log\Arhive\Device.log" -DestinationPath "E:\loguri\Log\Arhive\$inputID.zip" -Update
Remove-Item -Path "E:\loguri\Log\Arhive\Device.log" -Force
}
I'm using this script to convert DOC to HTML
param([string]$docpath,[string]$htmlpath = $docpath)
$srcfiles = Get-ChildItem $docPath -filter "*.doc"
$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatFilteredHTML");
$word = new-object -comobject word.application
$word.Visible = $False
function saveas-filteredhtml
{
$opendoc = $word.documents.open($doc.FullName);
$opendoc.saveas([ref]"$htmlpath\$doc.fullname.html", [ref]$saveFormat);
$opendoc.close();
}
ForEach ($doc in $srcfiles)
{
Write-Host "Processing :" $doc.FullName
saveas-filteredhtml
$doc = $null
}
$word.quit();
Unfortunately when I run it for the first time in the ISE console I get this error
Unable to find type [Microsoft.Office.Interop.Word.WdSaveFormat].
In F:\PS\NEW\main.ps1:108 car:29
+ ... = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFor ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (Microsoft.Offic...rd.WdSaveFormat:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
While if I run it from the same console again the second time it works fine.
How can I solve the problem? Thanks
In this forum they solve the problem:https://gallery.technet.microsoft.com/office/6f7eee4b-1f42-499e-ae59-1aceb26100de/view/Discussions
you add this lines at the beginning of your code:
$wdTypes = Add-Type -AssemblyName 'Microsoft.Office.Interop.Word' -Passthru
$wdSaveFormat = $wdTypes | Where {$_.Name -eq "wdSaveFormat"}
My approach is to get the latest ModifyTimeStamp after scanning on all DC's. The scenario in my code is:
First, I scan on the PDC to get the distinguishedName values, and after that I scan on all DC's also to get distinguishedName values, if they are -eq to each other, it will print the ModifyTimeStamp which means all ModifyTimeStamp values on each DC's will be stored in an arraylist. The arraylist will print the maximum values then on. As the following:
$TrustedDomain = "test.com"
$context = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext("domain",$TrustedDomain)
$D = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($context)
$PDC = $D.PdcRoleOwner
$ADSearch = New-Object System.DirectoryServices.DirectorySearcher
$ADSearch.SearchRoot ="LDAP://$PDC"
$ADSearch.SearchScope = "subtree"
$ADSearch.PageSize = 100
$ADSearch.Filter = "(&(objectCategory=person)(objectClass=user))"
foreach($pro in $properies)
{
$ADSearch.PropertiesToLoad.add($pro)| out-null
}
$userObjects = $ADSearch.FindAll()
$dnarr = New-Object System.Collections.ArrayList
Function modiScan{
$Searcher = New-Object System.DirectoryServices.DirectorySearcher
$Searcher.PageSize = 100
$Searcher.SearchScope = "subtree"
$Searcher.Filter = "(&(objectCategory=person)(objectClass=user))"
$Searcher.PropertiesToLoad.Add("distinguishedName")|Out-Null
$Searcher.PropertiesToLoad.Add("modifyTimeStamp")|Out-Null
forEach ($users In $userObjects)
{
$DN = $users.Properties.Item("distinguishedName")[0]
$dnarr.add($DN)|Out-Null
}
#$dnarr
foreach($dnn in $dnarr){
$lastmd = New-Object System.Collections.ArrayList
ForEach ($DC In $D.DomainControllers){
$Server = $DC.Name
$Base = "LDAP://$Server/"+$dnn
$Searcher.SearchRoot = $Base
$Results2 = $Searcher.FindAll()
ForEach ($Result2 In $Results2)
{
$DN2 = $Result2.Properties.Item("distinguishedName")[0]
if($DN2 -eq $dnn){
$modi = $Result2.Properties.Item("modifyTimeStamp")[0]
$lastmd.Add($modi)|Out-Null
}
}
}
$lastModi = ($lastmd |measure -max).maximum
if($lastModi -ne $null){
$lastModi = $lastModi.ToString("yyyy/MM/dd")
}
else{
$lastModi = "N/A"
}
$lastModi
}
}
modiScan
The error I've got is:
Exception calling "FindAll" with "0" argument(s): "Unknown error (0x80005000)"
At C:\Users\Ender\trustedScan.ps1:40 char:21
+ $Results2 = $Searcher.FindAll()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : COMException
I have executed on current Domain it worked like a charm. But when I try to put a trusted domain, it throws me that error.
I have following powershell script which should update my windows OS everytime I run it. Therefore I use the given windows API in order to search, download and install the updates. But somehow only searching for them actually works.
This is my script:
$global:scriptpath = $MyInvocation.MyCommand.Path
$global:dir = Split-Path $scriptpath
$global:logfile = "$dir\updatelog.txt"
write-host " Searching for updates..."
$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()
$result = $searcher.Search("IsInstalled=0 and Type='Software' and IsHidden=0")
if ($result.Updates.Count -eq 0) {
Write-Host "No updates to install"
} else {
$result.Updates | Select Title
}
$downloads = New-Object -ComObject Microsoft.Update.UpdateColl
foreach ($update in $result){
try {
$update.AcceptEula()
$Null = $downloads.Add($update)
} catch {}
}
$count = $result.Updates.Count
write-host ""
write-host "There are $($count) updates available."
write-host ""
read-host "Press Enter to download\install updates"
$downloader = $session.CreateUpdateDownLoader()
$downloader.Updates = $downloads
$downloader.Download()
$installs = New-Object -ComObject Microsoft.Update.UpdateColl
foreach ($update in $result.Updates){
if ($update.IsDownloaded){
$installs.Add($update)
}
}
$installer = $session.CreateUpdateInstaller()
$installer.Updates = $installs
$installresult = $installer.Install()
$installresult
But I get following error:
Exception calling "Download" with "0" argument(s): "Exception from HRESULT: 0x80240024"
+ $downloader.Download()
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
Somehow this line: $downloader.Updates = $downloads is not executed, but I don't know why. I also already tried running the script as an admin, didn't work either.
That error code is the WU_E_NO_UPDATE, described here. Basically it says that the Updates collection is not set or empty.
I posted this script the other day in an effort to discover a good way to change file extensions when "saving as." I had the problem licked, but as of this morning, the script will not run without errors. Here's the error message I'm getting:
Processing : C:\users\xxx\Desktop\ht\Automatic_Post-Call_Survey.htm
Exception calling "SaveAs" with "16" argument(s): "This is not a valid file name.
Try one or more of the following:
* Check the path to make sure it was typed correctly.
* Select a file from the list of files and folders."
At C:\users\xxx\Desktop\hd.ps1:11 char:20
+ $opendoc.saveas <<<< ([ref]"$docpath\$doc.FullName.doc", [ref]$saveFormat);
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
if "16" is the error code, that represents an inability to delete the directory...but it doesn't appear as if I'm asking for that at all--unless there's some default parameter in place somewhere. I'm pretty much baffled.anyone have any other ideas I can try out?
$docpath = "c:\users\xxx\desktop\do"
$htmPath = "c:\users\xxx\desktop\ht"
$srcfiles = Get-ChildItem $htmPath -filter "*.htm*"
$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatDocument");
$word = new-object -comobject word.application
$word.Visible = $False
$filename = ($_.fullname).substring(0,($_.FullName).lastindexOf("."))
function saveas-document {
$opendoc = $word.documents.open($doc.FullName);
$opendoc.saveas([ref]"$docpath\$filename", [ref]$saveFormat);
$opendoc.close();
}
ForEach ($doc in $srcfiles) {
Write-Host "Processing :" $doc.FullName
saveas-document
$doc = $null
}
$word.quit();
this should do what do you need, but is not the best design :)
$docpath = "c:\users\xxx\desktop\do"
$htmPath = "c:\users\xxx\desktop\ht"
$srcfiles = Get-ChildItem $htmPath -filter "*.htm*"
$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatDocument");
$global:word = new-object -comobject word.application
$word.Visible = $False
#$filename = ($_.fullname).substring(0,($_.FullName).lastindexOf("."))
function saveas-document ($docs) {
$opendoc = $word.documents.open($docs);
$savepath = $docs -replace [regex]::escape($htmPath),"$docpath"
$savepath = $savepath -replace '\.html*', '.doc'
$opendoc.saveas([ref]"$savepath", [ref]$saveFormat);
$opendoc.close();
}
ForEach ($doc in $srcfiles) {
Write-Host "Processing :" $doc.FullName
saveas-document -doc $doc.FullName
$doc = $null
}
$word.quit();