1: using System;
2: using System.IO;
3: using System.Reflection;
4: using System.Security;
5: using System.Text;
6: using Lapointe.SharePoint.STSADM.Commands.SPValidators;
7: using Microsoft.SharePoint;
8: using Microsoft.SharePoint.Administration;
9: using Microsoft.SharePoint.Search.Administration;
10: using Microsoft.SharePoint.Utilities;
11: using Lapointe.SharePoint.STSADM.Commands.OperationHelpers;
12:
13: namespace Lapointe.SharePoint.STSADM.Commands.WebApplications
14: {
15: public class CreateWebApp : SPOperation
16: {
17: /// <summary>
18: /// Initializes a new instance of the <see cref="CreateWebApp"/> class.
19: /// </summary>
20: public CreateWebApp()
21: {
22: SPParamCollection parameters = new SPParamCollection();
23: parameters.Add(new SPParam("url", "url", true, null, new SPUrlValidator()));
24: parameters.Add(new SPParam("directory", "dir", false, null, new SPNonEmptyValidator(),
25: "Please specify the virtual directory for the web application."));
26: parameters.Add(new SPParam("port", "p", false, "80", new SPIntRangeValidator(0, int.MaxValue),
27: "Please specify the port for the web application."));
28: parameters.Add(new SPParam("timezone", "tz", false, null, new SPIntRangeValidator(0, ushort.MaxValue)));
29: parameters.Add(new SPParam("description", "desc", false, null, new SPNullOrNonEmptyValidator()));
30: parameters.Add(new SPParam("sethostheader", "sethh", false, null, new SPNullOrNonEmptyValidator()));
31: parameters.Add(new SPParam("exclusivelyusentlm", "ntlm"));
32: parameters.Add(new SPParam("allowanonymous", "anon"));
33: parameters.Add(new SPParam("ssl", "ssl"));
34:
35: string normalizedDataSource;
36: string defaultDatabaseUsername;
37: string defaultDatabasePassword;
38: SPFarm local = SPFarm.Local;
39: if (local != null)
40: {
41: SPWebService service = local.Services.GetValue<SPWebService>();
42: normalizedDataSource = service.DefaultDatabaseInstance.NormalizedDataSource;
43: defaultDatabaseUsername = service.DefaultDatabaseUsername;
44: defaultDatabasePassword = service.DefaultDatabasePassword;
45: if ((normalizedDataSource == null) || (normalizedDataSource.Length == 0))
46: {
47: normalizedDataSource = Environment.MachineName;
48: }
49: }
50: else
51: {
52: Console.WriteLine(SPResource.GetString("NoFarmObject", new object[0]));
53: return;
54: }
55: if (defaultDatabaseUsername == null)
56: {
57: defaultDatabaseUsername = "";
58: }
59: if (defaultDatabasePassword == null)
60: {
61: defaultDatabasePassword = "";
62: }
63: parameters.Add(new SPParam("databaseserver", "ds", false, normalizedDataSource, new SPNonEmptyValidator()));
64: parameters.Add(new SPParam("databasename", "dn", false, null, new SPNullOrNonEmptyValidator()));
65: parameters.Add(new SPParam("databaseuser", "du", false, defaultDatabaseUsername, null));
66: parameters.Add(new SPParam("databasepassword", "dp", false, defaultDatabasePassword, null));
67:
68: parameters.Add(new SPParam("apidname", "apid", false, "DefaultAppPool", new SPNonEmptyValidator()));
69: parameters.Add(new SPParam("apidtype", "apidtype", false, "NetworkService",
70: new SPRegexValidator("^configurableid$|^networkservice$")));
71: parameters.Add(new SPParam("apidlogin", "apu", true, null, new SPNonEmptyValidator()));
72: parameters.Add(new SPParam("apidpwd", "app", true, null, new SPNonEmptyValidator()));
73:
74: parameters.Add(new SPParam("donotcreatesite", "nosite"));
75: parameters.Add(new SPParam("ownerlogin", "ol", true, null, new SPNonEmptyValidator()));
76: parameters.Add(new SPParam("ownername", "on", false, null, null));
77: parameters.Add(new SPParam("owneremail", "oe", true, null,
78: new SPRegexValidator(@"^[^ \r\t\n\f@]+@[^ \r\t\n\f@]+$")));
79: parameters.Add(new SPParam("sitetemplate", "st", false, null, new SPNullOrNonEmptyValidator()));
80: parameters.Add(new SPParam("lcid", "lcid", false, "0", new SPRegexValidator("^[0-9]+$")));
81:
82: StringBuilder sb = new StringBuilder();
83: sb.Append("\r\n\r\nCreates a web application.\r\n\r\nParameters:\r\n");
84: sb.Append("\t-url <url>\r\n");
85: sb.Append("\t[-directory <virtual directory path>]\r\n");
86: sb.Append("\t[-port <web application port>]\r\n");
87: sb.Append("\t[-ownerlogin <domain\\name>]\r\n");
88: sb.Append("\t[-owneremail <someone@example.com>]\r\n");
89: sb.Append("\t[-exclusivelyusentlm]\r\n");
90: sb.Append("\t[-ownername <display name>]\r\n");
91: sb.Append("\t[-databaseuser <database user>]\r\n");
92: sb.Append("\t[-databaseserver <database server>]\r\n");
93: sb.Append("\t[-databasename <database name>]\r\n");
94: sb.Append("\t[-databasepassword <database user password>]\r\n");
95: sb.Append("\t[-lcid <language>]\r\n");
96: sb.Append("\t[-sitetemplate <site template>]\r\n");
97: sb.Append("\t[-donotcreatesite]\r\n");
98: sb.Append("\t[-description <iis web site name>]\r\n");
99: sb.Append("\t[-sethostheader <host header name>]\r\n");
100: sb.Append("\t[-apidname <app pool name>]\r\n");
101: sb.Append("\t[-apidtype <configurableid/NetworkService>]\r\n");
102: sb.Append("\t[-apidlogin <DOMAIN\\name>]\r\n");
103: sb.Append("\t[-apidpwd <app pool password>]\r\n");
104: sb.Append("\t[-allowanonymous]\r\n");
105: sb.Append("\t[-ssl]\r\n");
106: sb.Append("\t[-timezone <time zone ID>]\r\n");
107:
108: Init(parameters, sb.ToString());
109: }
110:
111: #region ISPStsadmCommand Members
112:
113: /// <summary>
114: /// Gets the help message.
115: /// </summary>
116: /// <param name="command">The command.</param>
117: /// <returns></returns>
118: public override string GetHelpMessage(string command)
119: {
120: return HelpMessage;
121: }
122:
123: /// <summary>
124: /// Runs the specified command.
125: /// </summary>
126: /// <param name="command">The command.</param>
127: /// <param name="keyValues">The key values.</param>
128: /// <param name="output">The output.</param>
129: /// <returns></returns>
130: public override int Execute(string command, System.Collections.Specialized.StringDictionary keyValues,
131: out string output)
132: {
133: output = string.Empty;
134:
135:
136: Uri uri = new Uri(Params["url"].Value);
137:
138: SPWebApplicationBuilder builder = GetWebAppBuilder(uri);
139:
140: SPWebApplication app = builder.Create();
141:
142: ProvisionTimerJob(app, false);
143:
144: // Set the TimeZone of the Application
145: if (Params["timezone"].UserTypedIn)
146: app.DefaultTimeZone = ushort.Parse(Params["timezone"].Value);
147:
148: app.Update();
149: app.Provision();
150:
151:
152: // Upload the newly created WebApplication to the List 'Web Application List' in Central Administration:
153: SPWebService.AdministrationService.WebApplications.Add(app);
154:
155: if (!Params["donotcreatesite"].UserTypedIn)
156: {
157: uint nLCID = uint.Parse(Params["lcid"].Value);
158: string webTemplate = Params["sitetemplate"].Value;
159: string ownerLogin = Params["ownerlogin"].Value;
160: ownerLogin = Utilities.TryGetNT4StyleAccountName(ownerLogin, app);
161: string ownerName = Params["ownername"].Value;
162: string ownerEmail = Params["owneremail"].Value;
163:
164: app.Sites.Add(uri.AbsolutePath, null, null, nLCID, webTemplate, ownerLogin, ownerName, ownerEmail, null,
165: null,
166: null);
167: }
168:
169:
170: Console.WriteLine(SPResource.GetString("PendingRestartInExtendWebFarm", new object[0]));
171: Console.WriteLine();
172:
173: if (!Params["donotcreatesite"].UserTypedIn)
174: Console.WriteLine(SPResource.GetString("AccessSiteAt", new object[] {uri.ToString()}));
175: Console.WriteLine();
176:
177: return OUTPUT_SUCCESS;
178: }
179:
180: private SPWebApplicationBuilder GetWebAppBuilder(Uri uri)
181: {
182: SPWebApplicationBuilder builder = new SPWebApplicationBuilder(SPFarm.Local);
183:
184: //Set the Port and the RootDirectory where you want to install the Application, e.g:
185: builder.Port = int.Parse(Params["port"].Value);
186: if (Params["directory"].UserTypedIn)
187: builder.RootDirectory = new DirectoryInfo(Params["directory"].Value);
188:
189: // Set the ServerComment for the Application which will be the Name of the Application in the SharePoint-List And IIS. If you do not set this Property, the Name of the Application will be 'SharePoint - <Default given Portnumber from System>'
190: if (Params["description"].UserTypedIn)
191: builder.ServerComment = Params["description"].Value;
192:
193: // Create the content database for this Application
194: builder.CreateNewDatabase = true;
195: if (Params["databasename"].UserTypedIn)
196: builder.DatabaseName = Params["databasename"].Value;
197: if (Params["databaseserver"].UserTypedIn)
198: builder.DatabaseServer = Params["databaseserver"].Value;
199: if (Params["databaseuser"].UserTypedIn)
200: builder.DatabaseUsername = Params["databaseuser"].Value;
201: if (Params["databasepassword"].UserTypedIn)
202: builder.DatabasePassword = Params["databasepassword"].Value;
203:
204: // Host Header settings
205: if (Params["sethostheader"].UserTypedIn)
206: {
207: if (string.IsNullOrEmpty(Params["sethostheader"].Value))
208: builder.HostHeader = uri.Host;
209: else
210: builder.HostHeader = Params["sethostheader"].Value;
211: }
212: builder.DefaultZoneUri = uri;
213:
214:
215: // App pool settings
216: builder.ApplicationPoolId = Params["apidname"].Value;
217: if (Params["apidtype"].Value.ToLowerInvariant() == "networkservice")
218: builder.IdentityType = IdentityType.NetworkService;
219: else
220: {
221: builder.IdentityType = IdentityType.SpecificUser;
222: builder.ApplicationPoolUsername = Params["apidlogin"].Value;
223: builder.ApplicationPoolPassword = CreateSecureString(Params["apidpwd"].Value);
224: }
225:
226: // Some additional Settings
227: builder.UseNTLMExclusively = Params["exclusivelyusentlm"].UserTypedIn;
228: builder.AllowAnonymousAccess = Params["allowanonymous"].UserTypedIn;
229: builder.UseSecureSocketsLayer = Params["ssl"].UserTypedIn;
230: return builder;
231: }
232:
233: /// <summary>
234: /// Validates the specified key values.
235: /// </summary>
236: /// <param name="keyValues">The key values.</param>
237: public override void Validate(System.Collections.Specialized.StringDictionary keyValues)
238: {
239: bool isUserAccount;
240: if (Params["donotcreatesite"].UserTypedIn)
241: {
242: Params["ownerlogin"].Enabled = false;
243: Params["ownername"].Enabled = false;
244: Params["owneremail"].Enabled = false;
245: Params["sitetemplate"].Enabled = false;
246: Params["lcid"].Enabled = false;
247: }
248: else
249: {
250: if (Params["ownerlogin"].UserTypedIn)
251: {
252: string ownerLogin = Utilities.TryGetNT4StyleAccountName(Params["ownerlogin"].Value, null);
253: if (!SPUtility.IsLoginValid(null, ownerLogin, out isUserAccount))
254: throw new ArgumentException(
255: SPResource.GetString("InvalidLoginAccount", new object[] {ownerLogin}));
256: if (!isUserAccount)
257: throw new ArgumentException(SPResource.GetString("OwnerNotUserAccount", new object[0]));
258: }
259: }
260: if (Params["apidtype"].Value.ToLowerInvariant() == "networkservice")
261: {
262: Params["apidlogin"].Enabled = false;
263: Params["apidpwd"].Enabled = false;
264: }
265: else
266: {
267: if (Params["apidlogin"].UserTypedIn)
268: {
269: string apidlogin = Utilities.TryGetNT4StyleAccountName(Params["apidlogin"].Value, null);
270: if (!SPUtility.IsLoginValid(null, apidlogin, out isUserAccount))
271: throw new ArgumentException(
272: SPResource.GetString("InvalidLoginAccount", new object[] {apidlogin}));
273: }
274: }
275: base.Validate(keyValues);
276: }
277:
278: #endregion
279:
280: /// <summary>
281: /// Creates the secure string.
282: /// </summary>
283: /// <param name="strIn">The string to convert.</param>
284: /// <returns></returns>
285: internal static SecureString CreateSecureString(string strIn)
286: {
287: if (strIn != null)
288: {
289: SecureString str = new SecureString();
290: foreach (char ch in strIn)
291: {
292: str.AppendChar(ch);
293: }
294: str.MakeReadOnly();
295: return str;
296: }
297: return null;
298: }
299:
300: private static void ProvisionTimerJob(SPWebApplication application, bool resetIis)
301: {
302: if (SPFarm.Local.TimerService.Instances.Count > 1)
303: {
304: // SPWebApplicationProvisioningJobDefinition is an internal class so we need to use reflection to set it.
305:
306: // SPWebApplicationProvisioningJobDefinition definition = new SPWebApplicationProvisioningJobDefinition(application, resetIis);
307: Type SPWebApplicationProvisioningJobDefinition =
308: Type.GetType(
309: "Microsoft.SharePoint.Administration.SPWebApplicationProvisioningJobDefinition, Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
310:
311: ConstructorInfo SPWebApplicationProvisioningJobDefinitionConstructor =
312: SPWebApplicationProvisioningJobDefinition.GetConstructor(
313: BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
314: null,
315: new Type[] {typeof (SPWebApplication), typeof (bool)}, null);
316: object jobDef =
317: SPWebApplicationProvisioningJobDefinitionConstructor.Invoke(new object[] {application, resetIis});
318:
319:
320: // jobDef.Schedule = new SPOneTimeSchedule(DateTime.Now);
321: PropertyInfo scheduleProp = SPWebApplicationProvisioningJobDefinition.GetProperty("Schedule",
322: BindingFlags.
323: FlattenHierarchy |
324: BindingFlags.NonPublic |
325: BindingFlags.Instance |
326: BindingFlags.
327: InvokeMethod |
328: BindingFlags.
329: GetProperty |
330: BindingFlags.Public);
331:
332: scheduleProp.SetValue(jobDef, new SPOneTimeSchedule(DateTime.Now), null);
333:
334: // jobDef.Update();
335: MethodInfo update = SPWebApplicationProvisioningJobDefinition.GetMethod("Update",
336: BindingFlags.NonPublic |
337: BindingFlags.Public |
338: BindingFlags.Instance |
339: BindingFlags.InvokeMethod |
340: BindingFlags.FlattenHierarchy,
341: null,
342: new Type[] {}, null);
343:
344:
345: update.Invoke(jobDef, new object[] {});
346: }
347: SPAdministrationWebApplication local = SPAdministrationWebApplication.Local;
348: if (local != null)
349: {
350: local.RemoveAdministrativeTask("WSSCreateWebApplication");
351: }
352: }
353: }
354: }