Thursday, December 24, 2009

How to create a bootable installation CD/DVD in Windows

1) Download BBIE
2) extract bootable sector from a bootable disk
3) Download ImgBurn
4) Create a bootable image file

Run ImgBurn
Choose "Create image file from file/folders"
Include desired files and folders
Click "Advanced", "Bootable Disc" (sic), specify as "Boot Image" file the file you obtained in step 2).

Launch the process, it will result in a .img file.

5) Create CD/DVD

Relaunch ImgBurn
Choose "Write image file to disc"
Browse to the image file obtained in step 4).

If everything goes well, you should end up with a bootable CD/DVD.

Thursday, August 13, 2009

How to create a PFX file

makecert.exe -sv MyKey.pvk -n "CN=My Test Site" MyKey.cer -sky exchange

"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\pvk2pfx.exe" -pvk MyKey.pvk -spc MyKey.cer -pfx MyPFX.pfx -po

Note: "-sky exchange" avoids errors like "SSL Certificate add failed, Error: 1312"

Friday, June 5, 2009

SharePoint: Code for extending a web app

This doesn't claim to be the code to extend a web app, but more like a boilerplate that you can adapt to your own needs. I tried it with a generous matrix of parameters and works correctly, but I have no doubt that some combinations may cause issues.

        private static void ExtendWebApplication(SPWebApplication webapp, string name, int port, SPUrlZone zone, bool secure, bool useWindowsAuth, bool allowAnonymous, bool useClaims)
{
if (webapp == null)
{
throw (new ArgumentNullException("webapp"));
}

SPServerBinding serverBinding = null;
SPSecureBinding secureBinding = null;
if (secure)
{
secureBinding = new SPSecureBinding();
secureBinding.Port = port;
}
else
{
serverBinding = new SPServerBinding();
serverBinding.Port = port;
}

string extendedAppPath = webapp.IisSettings[SPUrlZone.Default].Path.ToString().Substring(0, webapp.IisSettings[SPUrlZone.Default].Path.ToString().LastIndexOf(@"\") + 1) + port.ToString();
SPIisSettings iisSettings = new SPIisSettings(
string.Format(CultureInfo.InvariantCulture, "{0} - {1}", name, port),
false,
true,
serverBinding,
secureBinding,
new DirectoryInfo(extendedAppPath));
iisSettings.DisableKerberos = !useWindowsAuth;
iisSettings.UseWindowsIntegratedAuthentication = useWindowsAuth;
iisSettings.AllowAnonymous = allowAnonymous;
webapp.IisSettings.Add(zone, iisSettings);
webapp.AlternateUrls.SetResponseUrl(new SPAlternateUrl(GetAlternateUrl(port, secure), zone));
webapp.AlternateUrls.Update();
webapp.UseClaimsAuthentication = useClaims;
webapp.Update();
webapp.ProvisionGlobally();
}

Tuesday, June 2, 2009

C#: Running PowerShell from C#

This is a class that allows to execute PowerShell scripts from C#



using System.Management.Automation;
using System.Management.Automation.Runspaces;

/// <summary>
/// PowerShellExecutor
/// </summary>
public class PowerShellExecutor
{
Runspace _runspace = null;
Pipeline _pipeline = null;

/// <summary>
/// .ctor
/// </summary>
public PowerShellExecutor()
{
_runspace = RunspaceFactory.CreateRunspace();
_runspace = RegisterCmdlets(_runspace, _runspace.CreatePipeline());
_pipeline = _runspace.CreatePipeline();
}

public void ClearErrors()
{
_pipeline = _runspace.CreatePipeline("$error.Clear()");
_pipeline.Invoke();
}

/// <summary>
/// ExecuteCmdlet
/// </summary>
/// <param name="command"></param>
/// <param name="rs"></param>
/// <param name="pipe"></param>
/// <returns></returns>
/// <example>
/// PowerShellExecutor p = new PowerShellExecutor();
/// Collection<PSObject> c = p.ExecuteCmdlet("$w = Get-Web 'MySite - 80'", null);
/// c = p.ExecuteCmdlet("[System.Console]::WriteLine($w)", null);
/// </example>
public Collection<PSObject> ExecuteCmdlet(string command)
{
// create pipeline
_pipeline = _runspace.CreatePipeline();

// add script to execute
_pipeline.Commands.AddScript(command);

// execute
Collection<PSObject> results = _pipeline.Invoke();
StringBuilder result = new StringBuilder();

// check results
if (results.Count == 0)
{
result = new StringBuilder();
result.Append("$error");
_pipeline = _runspace.CreatePipeline(result.ToString());
results = _pipeline.Invoke();
}

// return
return results;
}

/// <summary>
/// RegisterCmdlets
/// </summary>
/// <param name="runspace"></param>
/// <param name="pipeline"></param>
/// <returns></returns>
private Runspace RegisterCmdlets(Runspace runspace, Pipeline pipeline)
{
Collection<PSObject> results;
StringBuilder command = new StringBuilder();
runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
command.Append("Set-Alias powershell $env:windir\\System32\\WindowsPowerShell\\v1.0\\powershell.exe");
pipeline = runspace.CreatePipeline(command.ToString());
results = pipeline.Invoke();

command = new StringBuilder();
command.Append("Add-pssnapin Microsoft.SharePoint.PowerShell");
pipeline = runspace.CreatePipeline(command.ToString());
results = pipeline.Invoke();
return runspace;
}
}

Monday, June 1, 2009

Architectural Concerns

Cheat-sheet on things to have in mind when looking at a system from an architectural perspective:

Simplicity
Testability
Usability
Deployment
Ecosystem
Modularity
Diagnosibility
Performance
Manageability
Compatibility
Layering
Reliability
Accessibility
Serviceability
Extensibility
Dependencies
Security
Globalizability
Supportability
Programmability
Maintenance

Saturday, May 30, 2009

WCF: System.ServiceModel.FaultException: The message could not be processed

Problem: exception thrown when connecting to a WCF service

System.ServiceModel.FaultException: The message could not be processed. This is most likely because the action 'http://tempuri.org/IStockService/GetSymbolData' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding.

Solution: at least in my case, there was a mismatch between the binding specified in the client (SecurityMode.None) and the server (wsHttpBinding). After specifiying the right binding in the client (SecurityMode.Message), it worked correctly.

Tuesday, April 7, 2009

When to use AllowUnsafeUpdates, ValidateFormDigest() or else

For scenarios in which your code is processing a POST request, ValidateFormDigest() will, behind the scenes, set AllowUnsafeUpdates to true.

But some scenarios (e.g. web services) are not a POST request, therefore ValidateFormDigest() will fail.

So, here's a simple decision tree to help:

HttpContext.Current is null => Do nothing, no need to set AllowUnsafeUpdates to true nor to call ValidateFormDigest() because update will be carried out (e.g. code being called from an .exe from a cmd prompt)

HttpContext.Current is NOT null
- SPContext.Current is null => Need to set AllowUnsafeUpdates to true (e.g. web service)
- SPContext.Current is NOT null => Call ValidateFormDigest() (e.g. POST request processing)

Monday, April 6, 2009

SPSecurity.RunWithElevatedPrivileges() throws InvalidOperationException, "Operation is not valid due to the current state of the object."

There are several reasons for this to happen.

1) HttpContext.Current.User == null
2) code running under impersonation.

If it's 2), here's one recipe, save HttpContext, set it to null, restore it back:

            HttpContext prev = HttpContext.Current;
HttpContext.Current = null;
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
...
});
}
finally
{
HttpContext.Current = prev;
}

Friday, February 20, 2009

SQL Server: how to delete non-system databases from a cursor

DECLARE @name nvarchar(200)
DECLARE @stmt nvarchar(200)
DECLARE dbCursor CURSOR FOR SELECT D.name FROM sys.databases D where owner_sid <> 0x01
OPEN dbCursor
FETCH NEXT FROM dbCursor INTO @name
WHILE @@FETCH_STATUS = 0
BEGIN
--next IF is not needed, as cursor specifies that owner_sid <> 0x01 already
--IF @name <> 'master' and @name <> 'model' and @name <> 'msdb' and @name <> 'tempdb'
--BEGIN
PRINT 'Name = ' + @name
SET @stmt = 'DROP DATABASE "' + @name + '"'
PRINT 'stmt = ' + @stmt
EXECUTE sp_executesql @stmt
--END
FETCH NEXT FROM dbCursor INTO @name
END
CLOSE dbCursor
DEALLOCATE dbCursor



Notice couple of tips (at least for someone that doesn't write T-SQL every morning ☺):

- SQL syntax doesn't allow some statements to be run from inside a cursor, so you have to call sp_executesql store proc.
- since '-' is a reserved operator, you have to enclose the DB on quotes to successfully operate on a DB whose name contains '-' or other reserved operator.
- owner_sid <> 0x01 filters out system DB's (preferred over the commented IF)

Friday, January 30, 2009

SQL Server: how to get the sizes of the columns of a table

select C.name, C.max_length from sys.columns C
inner join
sys.tables T
on C.object_id = T.object_id and T.name = '<table name>'

SQL Server: how to see Log Transaction status

select name, log_reuse_wait, log_reuse_wait_desc from sys.databases

SQL Server: how to get the sizes of all tables

EXEC sp_MSforeachtable @command1="EXEC sp_spaceused '?'"