Skip to content
This repository was archived by the owner on Jan 19, 2021. It is now read-only.

Commit 3549b22

Browse files
committed
Merge pull request #52 from OfficeDev/dev
September master merge
2 parents 7c15b9d + 273d21d commit 3549b22

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1433
-219
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ UpgradeLog*.htm
197197
# Microsoft Fakes
198198
FakesAssemblies/
199199

200+
# App.Config files
201+
[Aa]pp.[Cc]onfig
202+
200203
# Node.js Tools for Visual Studio
201204
.ntvs_analysis.dat
202205

Binaries/PnPPowerShellCommands15.msi

12 KB
Binary file not shown.

Binaries/PnPPowerShellCommands16.msi

8 KB
Binary file not shown.

CONTRIBUTING.md

+51-9
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,57 @@ Please see following page for additional insights on the model.
2929
---
3030

3131

32+
##Code contributions
33+
In order to succesfully compile the PnP PowerShell solution you will _also_ have to download the [PnP-Sites-Core](https://github.com/OfficeDev/PnP-Sites-Core) repository and make the dev branch available. The PowerShell solution depends on it. In order to succesfully
34+
compile it, make sure that PnP-Sites-Core is located at the same level as PnP-PowerShell.
35+
36+
So:
37+
```
38+
c:\[YOUR REPO FOLDER]\PnP-Sites-Core
39+
c:\[YOUR REPO FOLDER]\PnP-PowerShell
40+
```
41+
42+
The reason for this is that the PnP-PowerShell library will have references to the release and debug builds of the PnP-Sites-Core library.
43+
44+
A few notes:
45+
###Every new cmdlet should provide help and examples###
46+
As documentation is autogenerated by building the solution, make sure that you include both help and examples, alike
47+
48+
```csharp
49+
[Cmdlet("Get", "SPOStoredCredential")]
50+
[CmdletHelp("Returns a stored credential from the Windows Credential Manager", Category = "Base Cmdlets")]
51+
[CmdletExample(Code = "PS:> Get-SPOnlineStoredCredential -Name O365",
52+
Remarks = "Returns the credential associated with the specified identifier",
53+
SortOrder = 1)]
54+
public class GetStoredCredential : PSCmdlet
55+
{
56+
}
57+
```
58+
###Most cmdlets will extend SPOWebCmdlet which provides a few helper objects for you to use, like SelectedWeb and ClientContext###
59+
As most cmdlets are 'web sensitive' (e.g. you can specify a -Web parameter to point to a different subweb), make sure that you use the correct ClientContext. When a user specifies the -Web parameter
60+
in a cmdlet that extens SPOWebCmdlet, the cmdlet will switch it's internal context to that web, reusing credentials. It is important to use the right context, and the easiest way to do that is to use
61+
62+
```csharp
63+
var context = SelectedWeb.Context;
64+
```
65+
###Cmdlets will have to work both on-premises and in the cloud###
66+
You can use preprocessor variables ("CLIENTSDKV15" and "CLIENTSDKV16") to build different cmdlets for the different targets. In cases where it is not possible to provide functionality for either the
67+
cloud or on-premises, make sure to remove the full cmdlet from the compiled solution by having #IF(!CLIENTSDKV15) or #IF(CLIENTSDKV15) as the _first line of the cmdlet, before using statements.
68+
Make the last line, after all code * The verb of a cmdlet (get-, add-, etc.) should follow acceptable cmdlet standards and should be part of one of the built in verbs classes (VerbsCommon, VerbsData, etc.):
69+
70+
```csharp
71+
#if !CLIENTSDKV15
72+
using Microsoft.SharePoint.Client;
73+
74+
public class MyCmdlet : SPOWebCmdlet
75+
{
76+
// cmdlet code omitted
77+
}
78+
#endif
79+
```
80+
81+
If only parts of a cmdlet require different behaviour based upon the different version of the SDK, you are recommended to use the #CLIENTSDKV15 preprocessor variable throughout your code to exclude or include certain code.
82+
3283
##Documentation contributions
3384
If you want to contribute to cmdlet documentation, please do not make a pull request to modify the actual files in the Documentation folder itself. Those files
3485
are automatically generated based upon comments in the actual classes. So if you want to modify documentation and or add an example of a cmdlet, navigate to the
@@ -37,12 +88,3 @@ corresponding class where the cmdlet is being implemented and add the comments t
3788
https://github.com/OfficeDev/PnP-PowerShell/blob/dev/Commands/Fields/AddField.cs
3889

3990
Notice the [CmdletHelp("")] and [CmdletExample()] class attributes that describe the cmdlet.
40-
41-
##Cmdlet contributions
42-
43-
A few notes:
44-
* Every new cmdlet should provide help and examples.
45-
* Most cmdlets will extend SPOWebCmdlet which provides a few helper objects for you to use.
46-
* Cmdlets will have to work both on-premises and in the cloud. You can use preprocessor variables ("CLIENTSDKV15" and "CLIENTSDKV16") to build different cmdlets for the different targets.
47-
* The verb of a cmdlet (get-, add-, etc.) should follow acceptable cmdlet standards and should be part of one of the built in verbs classes (VerbsCommon, VerbsData, etc.)
48-
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
$name = "officedevpnppowershellcommands15"
2-
$url = "https://github.com/OfficeDev/PnP-PowerShell/releases/download/v1.2/PnPPowerShellCommands15.msi"
2+
$url = "https://github.com/OfficeDev/PnP-PowerShell/releases/download/v1.3.2/PnPPowerShellCommands15.msi"
33
Install-ChocolateyPackage $name 'msi' '/quiet' $url
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
$name = "officedevpnppowershellcommands15"
2-
Uninstall-ChocolateyPackage $name 'msi' "https://github.com/OfficeDev/PnP-PowerShell/releases/download/v1.2/PnPPowerShellCommands15.msi /qn"
2+
Uninstall-ChocolateyPackage $name 'msi' "https://github.com/OfficeDev/PnP-PowerShell/releases/download/v1.3.2/PnPPowerShellCommands15.msi /qn"
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
$name = "officedevpnppowershellcommands16"
2-
$url = "https://github.com/OfficeDev/PnP-PowerShell/releases/download/v1.2/PnPPowerShellCommands16.msi"
2+
$url = "https://github.com/OfficeDev/PnP-PowerShell/releases/download/v1.3.2/PnPPowerShellCommands16.msi"
33
Install-ChocolateyPackage $name 'msi' '/quiet' $url
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
$name = "officedevpnppowershellcommands16"
2-
Uninstall-ChocolateyPackage $name 'msi' "https://github.com/OfficeDev/PnP-PowerShell/releases/download/v1.2/PnPPowerShellCommands16.msi /qn"
2+
Uninstall-ChocolateyPackage $name 'msi' "https://github.com/OfficeDev/PnP-PowerShell/releases/download/v1.3.2/PnPPowerShellCommands16.msi /qn"

Commands/Admin/NewTenantSite.cs

+6-18
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,31 @@ public class NewTenantSite : SPOAdminCmdlet
1515
[Parameter(Mandatory = true)]
1616
public string Title;
1717

18-
[Parameter(Mandatory = true, HelpMessage = @"Specifies the full URL of the new site collection. It must be in a valid managed path in the company's site.
19-
For example, for company contoso, valid managed paths are https://contoso.sharepoint.com/sites and
20-
https://contoso.sharepoint.com/teams.")]
18+
[Parameter(Mandatory = true, HelpMessage = @"Specifies the full URL of the new site collection. It must be in a valid managed path in the company's site. For example, for company contoso, valid managed paths are https://contoso.sharepoint.com/sites and https://contoso.sharepoint.com/teams.")]
2119
public string Url;
2220

2321
[Parameter(Mandatory = false)]
2422
public string Description = string.Empty;
2523

26-
[Parameter(Mandatory = false, HelpMessage = @"Specifies the user name of the site collection's primary owner. The owner must be a user instead of a security
27-
group or an email-enabled security group.")]
24+
[Parameter(Mandatory = false, HelpMessage = @"Specifies the user name of the site collection's primary owner. The owner must be a user instead of a security group or an email-enabled security group.")]
2825
public string Owner = string.Empty;
2926

30-
[Parameter(Mandatory = false, HelpMessage = @"Specifies the language of this site collection. For more information, see Locale IDs Assigned by Microsoft
31-
(http://go.microsoft.com/fwlink/p/?LinkId=242911) (http://go.microsoft.com/fwlink/p/?LinkId=242911).")]
27+
[Parameter(Mandatory = false, HelpMessage = @"Specifies the language of this site collection. For more information, see Locale IDs Assigned by Microsoft: http://go.microsoft.com/fwlink/p/?LinkId=242911Id=242911.")]
3228
public uint Lcid = 1033;
3329

34-
[Parameter(Mandatory = false, HelpMessage = @"Specifies the site collection template type. Use the Get-SPOWebTemplate cmdlet to get the list of valid
35-
templates. If no template is specified, one can be added later. The Template and LocaleId parameters must be a
36-
valid combination as returned from the Get-SPOnlineWebTemplate cmdlet.")]
30+
[Parameter(Mandatory = false, HelpMessage = @"Specifies the site collection template type. Use the Get-SPOWebTemplate cmdlet to get the list of valid templates. If no template is specified, one can be added later. The Template and LocaleId parameters must be a valid combination as returned from the Get-SPOnlineWebTemplate cmdlet.")]
3731
public string Template = "STS#0";
3832

3933
[Parameter(Mandatory = true, HelpMessage = "Use Get-SPOnlineTimeZone to retrieve possible timezone values")]
4034
public int TimeZone;
4135

42-
[Parameter(Mandatory = false, HelpMessage = @"Specifies the quota for this site collection in Sandboxed Solutions units. This value must not exceed the
43-
company's aggregate available Sandboxed Solutions quota. The default value is 0. For more information, see
44-
Resource Usage Limits on Sandboxed Solutions in SharePoint
45-
2010(http://msdn.microsoft.com/en-us/library/gg615462.aspx)
46-
(http://msdn.microsoft.com/en-us/library/gg615462.aspx).")]
36+
[Parameter(Mandatory = false, HelpMessage = @"Specifies the quota for this site collection in Sandboxed Solutions units. This value must not exceed the company's aggregate available Sandboxed Solutions quota. The default value is 0. For more information, see Resource Usage Limits on Sandboxed Solutions in SharePoint 2010 : http://msdn.microsoft.com/en-us/library/gg615462.aspx.")]
4737
public double ResourceQuota = 0;
4838

4939
[Parameter(Mandatory = false)]
5040
public double ResourceQuotaWarningLevel = 0;
5141

52-
[Parameter(Mandatory = false, HelpMessage = @"Specifies the storage quota for this site collection in megabytes. This value must not exceed the company's
53-
available quota.
54-
")]
42+
[Parameter(Mandatory = false, HelpMessage = @"Specifies the storage quota for this site collection in megabytes. This value must not exceed the company's available quota.")]
5543
public long StorageQuota = 100;
5644

5745
[Parameter(Mandatory = false)]

Commands/Base/ConnectSPOnline.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public class ConnectSPOnline : PSCmdlet
4444

4545
[Parameter(Mandatory = false, ParameterSetName = "Main", HelpMessage = "If you want to connect to your on-premises SharePoint farm using ADFS")]
4646
public SwitchParameter UseAdfs;
47-
47+
4848
[Parameter(Mandatory = false, ParameterSetName = ParameterAttribute.AllParameterSets, HelpMessage = "Specifies a minimal server healthscore before any requests are executed.")]
4949
public int MinimalHealthScore = -1;
5050

@@ -141,7 +141,7 @@ protected override void ProcessRecord()
141141
}
142142
SPOnlineConnection.CurrentConnection = SPOnlineConnectionHelper.InstantiateSPOnlineConnection(new Uri(Url), creds, Host, CurrentCredentials, MinimalHealthScore, RetryCount, RetryWait, RequestTimeout, SkipTenantAdminCheck);
143143
}
144-
144+
WriteVerbose(string.Format("PnP PowerShell Cmdlets ({0}): Connected to {1}", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(), Url));
145145
}
146146

147147
private PSCredential GetCredentials()

Commands/Base/SetTraceLog.cs

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using OfficeDevPnP.PowerShell.CmdletHelpAttributes;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Diagnostics;
5+
using System.Linq;
6+
using System.Management.Automation;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
10+
namespace OfficeDevPnP.PowerShell.Commands.Base
11+
{
12+
[Cmdlet(VerbsCommon.Set, "SPOTraceLog")]
13+
[CmdletHelp("Defines if tracing should be turned on. PnP Core, which is the foundation of these cmdlets utilizes the standard Trace functionality of .NET. With this cmdlet you can turn capturing of this trace to a log file on or off.", Category = "Base Cmdlets")]
14+
[CmdletExample(
15+
Code = @"PS:> Set-SPOTraceLog -On -LogFile traceoutput.txt",
16+
Remarks = @"This turns on trace logging to the file 'traceoutput.txt' and will capture events of at least 'Information' level.",
17+
SortOrder = 1)]
18+
[CmdletExample(
19+
Code = @"PS:> Set-SPOTraceLog -On -LogFile traceoutput.txt -Level Debug",
20+
Remarks = @"This turns on trace logging to the file 'traceoutput.txt' and will capture debug events.",
21+
SortOrder = 2)]
22+
[CmdletExample(
23+
Code = @"PS:> Set-SPOTraceLog -On -LogFile traceoutput.txt -Level Debug -Delimiter "",""",
24+
Remarks = @"This turns on trace logging to the file 'traceoutput.txt' and will write the entries as comma separated. Debug events are captured.",
25+
SortOrder = 3)]
26+
[CmdletExample(
27+
Code = @"PS:> Set-SPOTraceLog -Off",
28+
Remarks = @"This turns off trace logging. It will flush any remaining messages to the log file.",
29+
SortOrder = 3)]
30+
public class SetTraceLog : PSCmdlet
31+
{
32+
[Parameter(Mandatory = true, ParameterSetName = "On", HelpMessage = "Turn on tracing to log file")]
33+
public SwitchParameter On;
34+
35+
[Parameter(Mandatory = false, ParameterSetName = "On", HelpMessage = "The path and filename of the file to write the trace log to.")]
36+
public string LogFile;
37+
38+
[Parameter(Mandatory = false, ParameterSetName = "On", HelpMessage = "The level of events to capture. Possible values are 'Debug', 'Error', 'Warning', 'Information'. Defaults to 'Information'.")]
39+
public Core.Diagnostics.LogLevel Level = Core.Diagnostics.LogLevel.Information;
40+
41+
[Parameter(Mandatory = false, ParameterSetName = "On", HelpMessage = "If specified the trace log entries will be delimited with this value.")]
42+
public string Delimiter;
43+
44+
[Parameter(Mandatory = false, ParameterSetName = "On", HelpMessage = "Indents in the tracelog will be with this amount of characters. Defaults to 4.")]
45+
public int IndentSize = 4;
46+
47+
[Parameter(Mandatory = false, ParameterSetName = "On", HelpMessage = "Auto flush the trace log. Defaults to true.")]
48+
public bool AutoFlush = true;
49+
50+
[Parameter(Mandatory = true, ParameterSetName = "Off", HelpMessage = "Turn off tracing to log file.")]
51+
public SwitchParameter Off;
52+
53+
private const string LISTENERNAME = "PNPPOWERSHELLTRACELISTENER";
54+
protected override void ProcessRecord()
55+
{
56+
57+
if (ParameterSetName == "On")
58+
{
59+
var existingListener = Trace.Listeners[LISTENERNAME];
60+
if (existingListener != null)
61+
{
62+
existingListener.Flush();
63+
existingListener.Close();
64+
Trace.Listeners.Remove(existingListener);
65+
}
66+
67+
if (!string.IsNullOrEmpty(LogFile))
68+
{
69+
if (!System.IO.Path.IsPathRooted(LogFile))
70+
{
71+
LogFile = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, LogFile);
72+
}
73+
if (!string.IsNullOrEmpty(Delimiter))
74+
{
75+
DelimitedListTraceListener delimitedListener = new DelimitedListTraceListener(LogFile);
76+
delimitedListener.Delimiter = Delimiter;
77+
delimitedListener.TraceOutputOptions = TraceOptions.DateTime;
78+
delimitedListener.Name = LISTENERNAME;
79+
Trace.Listeners.Add(delimitedListener);
80+
Core.Diagnostics.Log.LogLevel = Level;
81+
}
82+
else
83+
{
84+
TextWriterTraceListener listener = new TextWriterTraceListener(LogFile);
85+
listener.Name = LISTENERNAME;
86+
Trace.Listeners.Add(listener);
87+
Core.Diagnostics.Log.LogLevel = Level;
88+
}
89+
}
90+
else
91+
{
92+
ConsoleTraceListener consoleListener = new ConsoleTraceListener(false);
93+
consoleListener.Name = LISTENERNAME;
94+
Trace.Listeners.Add(consoleListener);
95+
Core.Diagnostics.Log.LogLevel = Level;
96+
}
97+
Trace.AutoFlush = AutoFlush;
98+
Trace.IndentSize = IndentSize;
99+
}
100+
else
101+
{
102+
try
103+
{
104+
Trace.Flush();
105+
Trace.Listeners[LISTENERNAME].Close();
106+
Trace.Listeners.Remove(LISTENERNAME);
107+
}
108+
catch (Exception) { }
109+
}
110+
}
111+
}
112+
}

Commands/Branding/AddCustomAction.cs

+39-10
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@
44
using OfficeDevPnP.Core.Entities;
55
using OfficeDevPnP.PowerShell.CmdletHelpAttributes;
66
using OfficeDevPnP.PowerShell.Commands.Enums;
7+
using System.Linq;
78

89
namespace OfficeDevPnP.PowerShell.Commands
910
{
1011
[Cmdlet(VerbsCommon.Add, "SPOCustomAction")]
11-
[CmdletHelp("Adds a custom action to a web", Category = "Branding")]
12+
[CmdletHelp("Adds a custom action to a web", Category = "Branding")]
1213
public class AddCustomAction : SPOWebCmdlet
1314
{
15+
[Parameter(Mandatory = true)]
16+
public string Name = string.Empty;
17+
1418
[Parameter(Mandatory = true)]
1519
public string Title = string.Empty;
1620

@@ -23,14 +27,26 @@ public class AddCustomAction : SPOWebCmdlet
2327
[Parameter(Mandatory = true)]
2428
public string Location = string.Empty;
2529

26-
[Parameter(Mandatory = true)]
30+
[Parameter(Mandatory = false)]
2731
public int Sequence = 0;
2832

29-
[Parameter(Mandatory = true)]
33+
[Parameter(Mandatory = false)]
3034
public string Url = string.Empty;
3135

3236
[Parameter(Mandatory = false)]
33-
public List<PermissionKind> Rights = new List<PermissionKind>();
37+
public string ImageUrl = string.Empty;
38+
39+
[Parameter(Mandatory = false)]
40+
public string CommandUIExtension = string.Empty;
41+
42+
[Parameter(Mandatory = false)]
43+
public string RegistrationId = string.Empty;
44+
45+
[Parameter(Mandatory = false)]
46+
public PermissionKind[] Rights;
47+
48+
[Parameter(Mandatory = false)]
49+
public UserCustomActionRegistrationType RegistrationType;
3450

3551
[Parameter(Mandatory = false)]
3652
public CustomActionScope Scope = CustomActionScope.Web;
@@ -39,16 +55,29 @@ public class AddCustomAction : SPOWebCmdlet
3955
protected override void ExecuteCmdlet()
4056
{
4157
var permissions = new BasePermissions();
42-
foreach (var kind in Rights)
58+
if (Rights != null)
4359
{
44-
permissions.Set(kind);
60+
foreach (var kind in Rights)
61+
{
62+
permissions.Set(kind);
63+
}
4564
}
46-
var ca = new CustomActionEntity { Description = Description, Location = Location, Group = Group, Sequence = Sequence, Title = Title, Url = Url, Rights = new BasePermissions() };
4765

48-
foreach (var permission in Rights)
66+
var ca = new CustomActionEntity
4967
{
50-
ca.Rights.Set(permission);
51-
}
68+
Name = Name,
69+
ImageUrl = ImageUrl,
70+
CommandUIExtension = CommandUIExtension,
71+
RegistrationId = RegistrationId,
72+
RegistrationType = RegistrationType,
73+
Description = Description,
74+
Location = Location,
75+
Group = Group,
76+
Sequence = Sequence,
77+
Title = Title,
78+
Url = Url,
79+
Rights = permissions
80+
};
5281

5382
if (Scope == CustomActionScope.Web)
5483
{

0 commit comments

Comments
 (0)