I am creating a new EventLog EventSource, and I use my own custom set of categories.
I currently do this in C# code with the following:
var eventSourceData = new EventSourceCreationData(sourceName, logName)
{
CategoryCount = AllCategories.Count(),
CategoryResourceFile = resourceFilePath,
ParameterResourceFile = resourceFilePath,
MessageResourceFile = resourceFilePath
};
EventLog.CreateEventSource(eventSourceData);
I have now converted this to a powershell script like this:
New-eventlog -logname $Log -ComputerName $ComputerName -Source $Source -CategoryResourceFile $categoryDllPath -MessageResourceFile $categoryDllPath -ErrorVariable Err -CategoryCount 20
Notr -CategoryCount 20 at the end, my script fails on this argument saying it is not a valid parameter. (Which it seems not to be)
So my question is, using Powershell how can I provide the CategoryCount so that the logging works correctly?
Thanks so much.
The error message is A parameter cannot be found that matches parameter name 'CategoryCount'.
As far as I can see, New-EventLog doesn't support CategoryCount.
But you can still use .NET classes directly in Powershell, so something like this should work:
$eventSourceData = new-object System.Diagnostics.EventSourceCreationData("$SourceName", "$logName")
$eventSourceData.CategoryCount = 20
$eventSourceData.CategoryResourceFile = $CategoryDllPath
$eventSourceData.MessageResourceFile = $CategoryDllPath
If (![System.Diagnostics.EventLog]::SourceExists($eventSourceData.Source))
{
[System.Diagnostics.EventLog]::CreateEventSource($eventSourceData)
}
Related
I'm using the .NET client libraries for VSTS/TFS (https://learn.microsoft.com/en-us/vsts/integrate/concepts/dotnet-client-libraries?view=vsts) to retrieve a list of tasks for all Build Definitions for all Team Projects. I'm using the v16.139.0-preview version of the NuGet package Microsoft.TeamFoundation.ExtendedClient (I need to because I need to retrieve Release Definition workflow as well for which you need Microsoft.VisualStudio.Services.Release.Client which has a dependency requirement for the ExtendedClient). The server (on-prem) is a TFS 2017.2. In no way I'm able to retrieve the tasks/phases/process. This is my code:
VssConnection connection = new VssConnection(new Uri("http://tfsserver:8080/tfs/defaultcollection"), new VssClientCredentials());
ProjectHttpClient projectClient = connection.GetClient<ProjectHttpClient>();
IEnumerable<TeamProjectReference> projects = projectClient.GetProjects().Result;
BuildHttpClient buildClient = connection.GetClient<BuildHttpClient>();
foreach (var project in projects)
{
IPagedList<BuildDefinition> buildDefinitions = buildClient.GetFullDefinitionsAsync2(project: project.Name, name: null).Result;
foreach (BuildDefinition buildDefinition in buildDefinitions)
{
// get the tasks
}
}
I have tried to re-retrieve the Build Definition using buildClient.GetDefinitionAsync without additional effect
The "Steps" property (which is going to be deprecated) is always null
The "Process" property is empty
There is no "phases" property available (which seems logical looking at the options to have multiple phases in a Build Definition
There is a contract available for BuildDefinitionStep: https://learn.microsoft.com/en-us/vsts/extend/reference/client/api/tfs/build/contracts/builddefinitionstep?view=vsts
The REST API documentation doesn't have a property called "Step": https://learn.microsoft.com/en-us/rest/api/vsts/build/definitions/get?view=vsts-rest-4.1#builddefinition
Does anyone have an idea on how to solve this?
Just try below C# sample using .NET client libraries, test on TFS 2017.3 and VSTS, both work. (No TFS 2017.2 on my side, If I remember correctly, TFS 2017.2 has the similar build process with TFS 2015, It has no the "Process" and "phases" attribute. )
using System;
using Microsoft.TeamFoundation.Build.WebApi;
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
namespace RetrieveTaskList
{
class Program
{
static void Main(string[] args)
{
//For TFS :
var tfsUrl = "http://ws-tfs2017:8080/tfs/DefaultCollection";
var buildClient = new BuildHttpClient(new Uri(tfsUrl), new VssAadCredential());
//For VSTS:
//var tfsUrl = "https://{account}.visualstudio.com";
//var buildClient = new BuildHttpClient(new Uri(tfsUrl), new VssBasicCredential(string.Empty, "PAT here"));
var definitions = buildClient.GetFullDefinitionsAsync(project: "ScrumProject");
foreach (var definition in definitions.Result)
{
Console.WriteLine(string.Format("\n {0} - {1}:", definition.Id, definition.Name));
// Get BuildDefinitionStep to array, each of which has a task property that contains things like the name of the task and the inputs.
var tasks = definition.Steps.ToArray();
//Get each step/task from the array
foreach (var task in tasks)
{
Console.WriteLine(task.DisplayName);
}
}
Console.ReadLine();
}
}
}
You can also use the REST API to retrieve the list of tasks from a build definition.
PowerShell for example:
Param(
[string]$baseurl = "http://server:8080/tfs/DefaultCollection",
[string]$projectName = "ProjectName",
[string]$buildDefinitionID = "26",
[string]$user = "domain\user",
[string]$token = "password"
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$uri = "$baseurl/$($projectName)/_apis/build/definitions/$buildDefinitionID"
Write-Host $uri
$result = (Invoke-RestMethod -Uri $uri -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
$tasks = $result.process.phases.steps.displayName
foreach ($task in $tasks)
{
write-host $task
}
You can also try the REST Client, please reference this thread : Retrieve VSTS/TFS Build task name list
A bit late to the party, but if you're wanting to iterate over the Build tasks using the AzDO .NET Client library you need to cast the Process to a DesignerProcess/DockerProcess/YamlProcess.
var buildDefinitions = await _buildClient.GetFullDefinitionsAsync(project.Id);
foreach (var buildDefinition in buildDefinitions)
{
if (buildDefinition.Process != null && buildDefinition.Process is Microsoft.TeamFoundation.Build.WebApi.DesignerProcess designerProcess)
{
foreach (var phase in designerProcess.Phases)
foreach (var step in phase.Steps)
Console.WriteLine($"taskname={step.DisplayName}");
break;//lets exit the loop early
}
}
Demo repo, https://github.com/f2calv/azdo-api-net-client-issue
With the help of #Andy I was able to solve the problem. I used Fiddler call the REST Api (http://server:8080/tfs/DefaultCollection/MyProject/_apis/build/definitions/1) and read the JSON response. I discovered that the "build" property contains the collection of tasks. I fixed the PowerShell script provided by #Andy:
Param(
[string]$baseurl = "http://server:8080/tfs/DefaultCollection",
[string]$projectName = "MyProject",
[string]$buildDefinitionID = "530",
[string]$user = "domain\user",
[string]$token = "PersonalAccessToken"
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$uri = "$baseurl/$($projectName)/_apis/build/definitions/$buildDefinitionID"
Write-Host $uri
$result = (Invoke-RestMethod -Uri $uri -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
foreach ($task in $result.build)
{
Write-Host $task.displayName
}
I am trying to automate a process that gets and sets mailbox permissions using remote powershell via an automated exchange pipeline. The AccessRights property of the Get-MailboxPermission command output is of type Microsoft.Exchange.RecipientTasks.MailboxRights []. I cannot find this namespace anywhere on nuget and it does not appear to be part of the EWS api, as far as I can tell. Does anyone know where this namespace can be found so I can reference it in my project, or if there is a way to cast the output as a standard object type?
Thank you
In Remote Powershell you have deserialized types https://blogs.msdn.microsoft.com/powershell/2010/01/07/how-objects-are-sent-to-and-from-remote-sessions/ so the server side types aren't what you should be using at that point. All you need to do is something like
Command getmbPerms = new Command("Get-MailboxPermission");
getmbPerms.Parameters.Add("Identity", Mailbox);
Pipeline plPileLine = Runspace.CreatePipeline();
plPileLine.Commands.Add(getmbPerms);
Collection<PSObject> RsResultsresults = plPileLine.Invoke();
foreach (PSObject obj in RsResultsresults)
{
Console.WriteLine(obj.Properties["User"].Value.ToString());
PSObject AccessRights = (PSObject)obj.Properties["AccessRights"].Value;
System.Collections.ArrayList AccessRightsCol = (System.Collections.ArrayList)AccessRights.BaseObject;
foreach (String Permission in AccessRightsCol)
{
Console.WriteLine(Permission);
}
}
plPileLine.Stop();
and then just parse the Enums out of the String. When you Set rights for a user the AccessRights parameter is just a string that matches the server side enums.
Command AddPermissions = new Command("Add-MailboxPermission");
AddPermissions.Parameters.Add("Identity", Mailbox);
AddPermissions.Parameters.Add("User", UserName);
AddPermissions.Parameters.Add("AccessRights", "FullAccess");
AddPermissions.Parameters.Add("AutoMapping", false);
If you implement a custom PowerShell Host with System.Management.Automation (SMA), all of the automatic variables are avaialable, except it seems that $PROFILE is empty. How would one go about recreating it?
Is it always in UserProfile + \Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1? Or do I need to be worried about it being in other places?
To clarify, I only care about CurrentUserCurrentHost profile.
Details
Given this PowerShell script:
Write-Output "_Profiles_"
Write-Output "CurrentUserCurrentHost = '$($Profile.CurrentUserCurrentHost)'"
Write-Output "CurrentUserAllHosts = '$($Profile.CurrentUserAllHosts)'"
Write-Output "AllUsersCurrentHost = '$($Profile.AllUsersCurrentHost)'"
Write-Output "AllUsersAllHosts = '$($Profile.AllUsersAllHosts)'"
Running it against system PowerShell has the following output:
_Profiles_
CurrentUserCurrentHost = 'C:\Users\rob\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1'
CurrentUserAllHosts = 'C:\User\rob\Documents\WindowsPowerShell\profile.ps1'
AllUsersCurrentHost = 'C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps1'
AllUsersAllHosts = 'C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1'
Running it with a Custom C# PowerShell Host (a System.Management.Automation.Host.PSHost implementation) shows:
_Profiles_
CurrentUserCurrentHost = ''
CurrentUserAllHosts = ''
AllUsersCurrentHost = ''
AllUsersAllHosts = ''
Background
https://github.com/chocolatey/choco/issues/667
This has been tested in PowerShell v3 / System.Managment.Automation (SMA) v3 but it could easily be proven out in other PowerShell versions.
As a possible fix, this is what I've come up with. However it does mean that $profile is always expected to be in the Documents folder.
var documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments, Environment.SpecialFolderOption.DoNotVerify);
var currentUserCurrentHostProfile = _fileSystem.combine_paths(documentsFolder, "WindowsPowerShell\\Microsoft.PowerShell_profile.ps1");
var profileFix = #"
if ((Test-Path(""{0}"")) -and ($profile -eq $null -or $profile -eq '')) {{
$global:profile = ""{1}""
}}
".format_with(documentsFolder, currentUserCurrentHostProfile);
pipeline.Commands.Add(new Command(profileFix, isScript: true, useLocalScope: false));
This is done this way due to special accounts like LocalSystem that would not have a profile folder.
Note: .format_with is a string formatter, so the {{ and }} you see will be converted to { and } when it finishes the string formatting.
Remove-NetEventSession is a powershell cmdlet that removes a network event session.
It's usually used after Stop-NetEventSession and Get-NetEventSession:
$session = Get-NetEventSession
Stop-NetEventSession $session.Name
Remove-NetEventSession $session.Name
Is there a way to achieve the same result using .Net? (Not by executing a powershell script)
Yes, there is.
Using the WMI API for .Net (System.Management) you can manipulate the MSFT_NetEventSession instance.
The following example gets the running session (there can be only one), stops it if it's running and removes it:
var netEventSession = new ManagementClass("/root/standardcimv2:MSFT_NetEventSession").
GetInstances().
Cast<ManagementObject>().
SingleOrDefault();
if (netEventSession != null)
{
if ((byte)netEventSession["SessionStatus"] == 0)
{
netEventSession.InvokeMethod("Stop", null, null);
}
netEventSession.Delete();
}
I have recently began using C# to invoke powershell scripts, with some success :)
$spWeb = Get-SPWeb -Identity http://127.0.0.1
$listTemplate = [Microsoft.SharePoint.SPListTemplateType]::DocumentLibrary
$spWeb.Lists.Add($args, "", $listTemplate) > $myDirectory
$spWeb.Lists.Add returns a SharePoint GUID.
Question:
I simply wish to pass in the directory/filename in which the GUID will
be written. How could that be done?
I have posted on the MSDN forums here: http://goo.gl/5p0oz but have continued my search on stackoverflow due to a seemingly dead end thread. This post is a cumulative gathering of the information found through MSDN responses.
You can try using the Set-Content cmdlet instead, like this. You need to pass the $myFile as a string and Set-Content will do the rest for you -
Inside your script i.e. MyScript.ps1 here, you will have this piece of code -
param([string]$parameter, [string]$myFile)
try
{
$spWeb = Get-SPWeb -Identity http://127.0.0.1
$listTemplate = [Microsoft.SharePoint.SPListTemplateType]::DocumentLibrary
$guid = $spWeb.Lists.Add($parameter, "", $listTemplate)
$guid | Set-Content $myFile
}
catch
{
throw ("Failed. The error was: '{0}'." -f $_ )
}
How to Run:
Open Powershell Prompt and type this
.\MyScript.ps1 "someparam1" "D:\Output.txt"
C# Bit -
private PowerShell _ps;
_ps = PowerShell.Create();
var parameter = new List<string>
{
parameter,
myFile
};
var sr = new StreamReader(#"C:\MyScript.ps1");
_ps.AddScript(sr.ReadToEnd()).AddParameters(parameter);
_ps.Invoke();