There is file named status.html which is used as a loadbalancer between WFE's on SharePoint servers. My query is I want to come up with a script or a mechanism that will trigger a mail as soon as this file is edited by someone.
Is it possible?
In my research I have found this script:
$ACL = new-object System.Security.AccessControl.DirectorySecurity
$AccessRule = new-object System.Security.AccessControl.FileSystemAuditRule("domain\seitconsult","Modify","success")
$ACL.SetAuditRule($AccessRule)
$ACL | Set-Acl "C:\windows\system32\cmd.exe"
But I'm not sure if that will work. Also, how can trigger an email using this script?
I see two ways to achieve your goal:
Attach a "send an e-mail" task to the event in question:
Open the Event Viewer (eventvwr.msc) and select an event you want to be notified about.
Click Action → Attach Task To This Event…
Step through the wizard and select Send an e-mail in the Action section.
Fill in the details and finish the wizard.
See here for more information.
Set up a FileSystemWatcher:
$folder = 'C:\your\html\folder'
$file = 'status.html'
$from = 'monitor#example.com'
$to = 'you#example.com'
$subject = "$file was modified"
$monitor = New-Object IO.FileSystemWatcher $folder, $file -Property #{
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
Register-ObjectEvent $monitor Changed -SourceIdentifier FileChanged -Action {
$name = $Event.SourceEventArgs.FullPath
$reader = New-Object System.IO.StreamReader($name)
$msg = $reader.ReadToEnd()
Send-MailMessage -From $from -To $to -Subject $subject -Body $msg
$reader.Close()
}
However, since the NotifyFilters don't include the username you need to extract that from the respective audit event in the eventlog as described here.
The watcher can be removed via its source identifier:
Unregister-Event -SourceIdentifier FileChanged
Related
I am simply trying to connect to a different SharePoint site. This code works perfectly with a specific site but when using a different site with the correct permissions to the site and site list, I receive the following error:
format-default: The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.
If the user has full control on the SharePoint list as well as the SharePoint site, why isn't the connection initialized?
I have stepped through the code line by line to see what is being stored to each variable and find that the code throws the error at the following line:
$sharepointlistitems = Get-ListItems -Context $Context -ListTitle $ListName
Here is the code from start to finish for accessing the site. The commented out site works perfectly with the code as is:
[Reflection.Assembly]::LoadFile(([System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client").location))
[Reflection.Assembly]::LoadFile(([System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.runtime").location))
$admincreds = Get-Credential
$SPCredentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($admincreds.UserName, $admincreds.Password)
######### Create Sharepoint List Functions ######################################################################
#Function to get items that are not processed
Function Get-ListItems([Microsoft.SharePoint.Client.ClientContext]$Context, [String]$ListTitle) {
$list = $Context.Web.Lists.GetByTitle($ListTitle)
$qry = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery()
#In future query by status to avoid slowing down of program
$items = $list.GetItems($qry)
$Context.Load($items)
$Context.ExecuteQuery()
return $items
}
#Function to update item status
Function Set-ListItemByID([Microsoft.SharePoint.Client.ClientContext]$Context, [String]$ListTitle, [int]$ItemId, [string]$Status) {
$list = $Context.Web.Lists.GetByTitle($ListTitle)
$listitem = $list.GetItemById($ItemId)
$listitem["AutoAccountCreationStatus"] = $Status
$listitem.Update();
$Context.ExecuteQuery()
}
########################## Step 1: Read from SharePoint List and add to an array ###########################################
#Sets Site, sets list of interest, creates array
#"https://<sitename>.sharepoint.com/sites/Home/TeamSite"
$SiteUrl = "https://<sitename>.sharepoint.com/sites/InfTech"
$ListName = "New Users"
#Setup the context
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)
$Context.Credentials = $SPCredentials
#Getting items from list
$sharepointlistitems = Get-ListItems -Context $Context -ListTitle $ListName
$sharepointlistitems = $sharepointlistitems | where {$_['AutoAccountCreationStatus'] -eq 'Received'}```
I use Power GUI Script editor to debug PowerShell script usually, we could monitor the variables, it's helpful for troubleshooting.
Or, you could use PnP PowerShell instead,demo
I wants to checkout the branch and commit the code changes using powershell script. This powershell script will be called from c# code.
But some times i'm getting the following issue
fatal: remote error: CAPTCHA required Your Bitbucket account has been
locked. To unlock it and log in again you must solve a CAPTCHA. This
is typically caused by too many attempts to login with an incorrect
password. The account lock prevents your SCM client from accessing
Bitbucket and its mirrors until it is solved, even if you enter your
password correctly.
If i logout in browser and login again by entering the CAPTCHA it is working fine. But if i host my application on server and if issue occurs, Logging out and login again is not the proper fix.
Can you please suggest good approach of handling this issue.
My Powershell code for Cloning the branch:
param(
[parameter(position=0)]
[string]$checkoutDirectory,
[parameter(position=1)]
[string]$checkoutBranch
)
function CheckoutTheCode($checkoutRepoUrl, $checkoutDirectory, $checkoutBranch)
{
[hashtable]$Return = #{}
try
{
if(Test-Path -Path $checkoutDirectory )
{
Remove-Item -Recurse -Force $checkoutDirectory
}
New-Item -ItemType directory -Path $checkoutDirectory
# Cloning
git clone --single-branch -b $checkoutBranch $checkoutRepoUrl $checkoutDirectory
$Return.Branch = $checkoutBranch
$Return.Directory = $checkoutDirectory
$Return.Status = $true
$Return.Message = "Success"
}
catch
{
$Return.Message = $Error[0].Exception
$Return.Status = $false
}
Return $Return
}
My Powershell code for Commit changes:
param(
[parameter(position=0)]
[string]$checkoutDirectory,
[parameter(position=1)]
[string]$commitMessage
)
function CommitTheCode($checkoutDirectory, $commitMessage)
{
[hashtable]$Return = #{}
try
{
cd $checkoutDirectory
git add .
git commit -m $commitMessage
git push
$Return.Status = $true
$Return.Message = "Success"
}
catch
{
$Return.Message = $Error[0].Exception
$Return.Status = $false
}
Return $Return
}
CommitTheCode $checkoutDirectory $commitMessage
The following steps worked for me (without asking a Bitbucket admin to click a button)
For Windows,
go to the credential manager (you can find this by searching for it in Start menu)
remove all credentials related to your bitbucket account
try again with your script.
I have the following problem:
When a user logs on over citrix, the logon script writes to a network file
Once the file has been written to, notify the local machine so that it can perform some operations
Once this is done, restart the session (I know how to do this part, my difficulty is with monitoring a network file from a locally stored FileWatcher and then running a local exe)
I plan to achieve this by:
Registering an ActiveEventScriptConsumer on the machine, which will monitor a file and then run an executable once it is modified
The first actions the exe takes is to sleep for 5 minutes, and then perform the actions I need it to do
Constraints
The issue I have is that ActiveEventScriptConsuemrs can't use the Wscript object, meaning I can't run an exe with:
objShell.Run("C:\MyProgram.exe")
Is there some other way of running an executable from vbscript which can be done from an EventConsumer? Alternatively, am I able to register this subscription where the script run uses something other than VBScript?
I would include the Wait in my logons script, but I can't delay the end of this because this causes my group policies to run 5 minutes after logon!
I tried having a look at running a batch file from the VBS, but this also uses WScript.
The executable is checking for something which occurs when a (Citrix) session begins, so I can't use regular windows logon as a trigger because sometimes the user will log onto a session even though the machine itself has been logged on for some time.
Any help is much appreciated!
Event Subscription Code:
$Computername = $env:COMPUTERNAME
$query = #"
SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE TargetInstance ISA 'CIM_DataFile' AND TargetInstance.Name='C:\\test\\filewatching\\tester.txt'
"#
$instanceFilter = ([WMICLASS]"\\$Computername\root\subscription:__EventFilter").CreateInstance()
$instanceFilter.QueryLanguage = 'WQL'
$instanceFilter.Query = $query
$instanceFilter.Name = 'EventFilterNameHere'
$instanceFilter.EventNameSpace = 'root/CIMV2'
$result = $instanceFilter.Put()
$script =
#"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("c:\test\filewatching\Log.log", 8, True)
objFile.WriteLine "1"
Dim objShell
Set objShell = WScript.CreateObject( "WScript.Shell" )
objShell.Run("C:\MyProgran.exe")
Set objShell = Nothing
objFile.WriteLine "2"
objFile.Close
"#
$instanceConsumer = ([wmiclass]"\\$Computername\root\subscription:ActiveScriptEventConsumer").CreateInstance()
$instanceConsumer.Name = 'ConsumerNameHere'
$instanceConsumer.ScriptingEngine = 'VBScript'
$instanceConsumer.ScriptFilename = ''
$instanceConsumer.ScriptText = $script
$instanceConsumer.Put()
[object]$Filter = (Get-WMIObject -Computername $Computername -Namespace root\Subscription -Class __EventFilter | Sort Name)
[object]$Consumer = (Get-WMIObject -Computername $Computername -Namespace root\Subscription -Class __EventConsumer | Sort Name)
$instanceBinding = ([wmiclass]"\\$Computername\root\subscription:__FilterToConsumerBinding").CreateInstance()
$instanceBinding.Filter = $Filter
$instanceBinding.Consumer = $Consumer
$instanceBinding.Put()
This is not possible using this type of event consumer. This is because the ActiveScriptEventConsumer doesn't allow any screen interaction except for basic message boxes:
Docs
When WMI is run as a service, scripts run by ActiveScriptEventConsumer do not generate screen output. Scripts that use MsgBox do run, but they do not display information on the screen. Running the WMI service as an executable file is not supported, but WMI allows scripts that use the MsgBox function to display output or accept user input. None of the methods provided by the WScript object can be used because ActiveScriptEventConsumer does not use Windows Script Host (WSH).
Another option would be to use CSCript, which only uses the command line, but this also doesn't support visual activity (only command-line), so for my purposes this will not work.
I created an High-Trust add-in for SharePoint 2013 with custom ribbon action and custom menu action.
For this, I have an ASP.NET MVC WebSite with the methods in the controller which match with the virtual urls put as custom action url. So, in the different elements.xml files, I filled action urls using the token 'remoteUrl', so no problem with the mapping.
When i create a package with VS2013, I write the url of my website which is on VM reachable from SP Server, and the client ID (I got from SP while registring my app). When I click on 'Finish', VS2013 generates a file '.app' which can be imported in SP online store or SP internal store.
Here is my problem, if I need to change the address of my website (which is stored in the app file, VS2013 just replaces the token 'RemoteUrl' with the url I give to it), is there any clean way to update the app file or may be if possible, directly the app stored in the SP application store (local to the server) ?
I found nothing for this problem. I saw few things about updating app with events and web services, but I didn't understood.
[EDIT] : I didn't understood that I have to change app version each time I need to update it that's why It didn't worked. Also, it seems that there is no other way to update the url in app file than modifying the AppManifest.xml in app file (which is a zip).
In one of my projects we used to do it with the following PowerShell script. It extracted the app file (it's just a ZIP) and modified multiple nodes in the manifest XML.
For packaging it uses a local copy of 7zip.
function ModifyAppPackage($appPackagePath, $applicationUrl, $clientId){
[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem");
$item = get-item $appPackagePath;
$zipFilePath = Join-Path $item.Directory.FullName $($item.BaseName + ".zip");
Copy-Item $item $zipFilePath;
$unzipDirectory = Join-Path $PSScriptRoot "\Temp";
New-Item -ItemType Directory -Force -Path $unzipDirectory;
if (Test-Path -Path $unzipDirectory\*)
{
Remove-Item $unzipDirectory\* -Force -Confirm:$false -Recurse:$true;
}
[System.IO.Compression.ZipFile]::ExtractToDirectory($zipFilePath, $unzipDirectory);
$modifiedFile = Join-Path $unzipDirectory "modified.txt"
if (Test-Path -Path $modifiedFile)
{
$modifiedContent = Get-Content $modifiedFile
if ($modifiedContent -eq $applicationUrl)
{
Remove-Item $unzipDirectory -Confirm:$false -Recurse:$true;
Remove-Item $zipFilePath;
return;
}
Remove-Item $modifiedFile;
}
$modifiedFileContent = $applicationUrl;
$modifiedFileContent >> $modifiedFile;
$manifestFileName = "AppManifest.xml";
$manifestFilePath = Join-Path $unzipDirectory $manifestFileName;
$manifestXml = [xml](get-content $manifestFilePath);
$nameSpaceManager = New-Object System.Xml.XmlNamespaceManager($manifestXml.NameTable);
$nameSpaceManager.AddNamespace("ns", $manifestXml.DocumentElement.NamespaceURI);
$startPageElement = $manifestXml.SelectSingleNode("/ns:App/ns:Properties/ns:StartPage", $nameSpaceManager);
$StartPage = $applicationUrl + "?{StandardTokens}"
$startPageElement.'#text' = $StartPage
$InstalledEventEndpointElement = $manifestXml.SelectSingleNode("/ns:App/ns:Properties/ns:InstalledEventEndpoint", $nameSpaceManager);
$InstalledEventEndpoint = $applicationUrl + "/Services/AppEventReceiver.svc"
$InstalledEventEndpointElement.'#text' = $InstalledEventEndpoint
$clientIdElement = $manifestXml.SelectSingleNode("/ns:App/ns:AppPrincipal/ns:RemoteWebApplication", $nameSpaceManager);
$clientIdElement.ClientId = $clientId;
$manifestXml.Save($manifestFilePath);
if (Test-Path -Path $zipFilePath)
{
Remove-Item $zipFilePath;
}
$pathToZipExe = $("$PSScriptRoot\7za.exe");
[Array]$arguments = "a", "-tzip", "$zipFilePath", "$unzipDirectory\*.*", "-r";
& $pathToZipExe $arguments;
# Cleanup
Remove-Item $unzipDirectory -Confirm:$false -Recurse:$true;
Remove-Item $appPackagePath -Confirm:$false;
# Rename new zip to .app
Rename-Item $zipFilePath $appPackagePath -Force -Confirm:$false;
return $true;
}
I think it would be possible to store the url in one of custom list in the app. Refer the url from the list. Whenever you need to change the url it can be done from the app itself.
When viewing an Event Logs properties (in Server 2008) you can set three actions for what to happen when the maximum event log size has been reached:
Overwrite events as needed
Archive the log when full
Do not overwrite events
Using Powershell I can use limit-eventlog to set the event log retention to set the OverflowAction to DoNotOverwrite or OverwriteAsNeeded, but I cannot seem to be able to get the Archive the log when full action selected.
Any ideas how I could select this option via powershell?
The only way (IMO) is to modifying the registry. Here an example to set 'Archive the log when full' action for the Application log:
new-ItemProperty -path HKLM:\SYSTEM\CurrentControlSet\services\eventlog\Application `
-name AutoBackupLogFiles -Value 1 -PropertyType 'dword'
if the options have been selected previously, the key is already present so just need set to 1 the key value:
set-ItemProperty -path HKLM:\SYSTEM\CurrentControlSet\services\eventlog\Application `
-name AutoBackupLogFiles -Value 1