How to Clear Archive & Read-only flags on Files in Windows in Bulk
I ran into an issue where I had to move files from one system to another and was running into issues because files had been set as read-only, had the archive flag set, or both. It was causing the system to skip files which wasn’t acceptable. Normally you could just use Windows to clear it in bulk, but that could potentially mess up file permissions. I needed a way to automatically just clear all flags but respect permissions.
I did some searching and didn’t find a utility that would do the job and most of the solutions I found required Powershell which wasn’t available on the system I was on. I ended up writing a quick console application in C# to do the trick. I’ve made it free and open sourced it in case anyone wants to use it.
If you need just the app, you can find the release build here with instructions. The app also prompts for input to make things a bit easier to use. There’s no install, no tracking or metrics, or anything else related to privacy concerns in this app. It’s a simple throwaway utility to get the job done and move on.
https://github.com/gregvarghese/clearflags/releases/tag/1.0.0
If you want to see the source code, that is available here:
https://github.com/gregvarghese/clearflags/
Please note that I did this in about 10 minutes for my own use so error handling is pretty much non-existent. I mention this because I did run into one issue where Windows was somehow seeing a folder with files in it as a file and it couldn’t be deleted or renamed and the utility couldn’t get past it until it was resolved. I didn’t spend much time debugging and just used my Mac to rename the folder and Windows was able to recognize it after the change, so the utility was able to continue processing.
How to Automate Sending Emails through Outlook interop using C#
I was tasked with a tricky issue in sending emails. Due to security concerns, the client’s IT team was not willing to share SMTP information for their mail settings and was only willing to set up an account in Outlook directly on a dedicated machine without sharing the password with us to send the emails. The client’s ask was to send emails through Outlook without letting users see the emails or Outlook itself.
Installing Office Interop for Outlook
Sending emails through Outlook can be done using Microsoft.Office.Interop.Outlook but the documentation is really lacking. If you need to do the same, I hope this will save you the hours of time it took me to figure out what ends up not being complex code.
Create a new desktop application project in Visual Studio. Install the Microsoft Office Interop for Outlook. I used the NuGet package manager to install it since it wasn’t present on my system:
Install-Package Microsoft.Office.Interop.Outlook
Automating E-mails using C#
I created a static class to send the email through Outlook. Note that my error handling code was replaced with Debug.Writeline. Remember to modify it to handle errors or implement logging so it doesn’t fail silently.
Email.cs:
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Outlook;
using Exception = System.Exception;
namespace Email.classes
{
public class Email
{
public static void SendWithEmbeddedImages(string to, string subject, string htmlMessage)
{
var missing = Type.Missing;
Application oOutlook = null;
NameSpace oNS = null;
Folder oCtFolder = null;
Items oCts = null;
MailItem msg = null;
var sHeaderPath = Path.Combine(Environment.CurrentDirectory, "emails", "header.jpg");
var sLogoPath = Path.Combine(Environment.CurrentDirectory, "emails", "logo.jpg");
try
{
// Create an Outlook application.
oOutlook = new Application();
// Get the namespace.
oNS = oOutlook.GetNamespace("MAPI");
//Assumes MAPI profile name is Outlook
oNS.Logon("Outlook", missing, false, true);
msg = (MailItem) oOutlook.CreateItem(OlItemType.olMailItem);
var attachHeader = msg.Attachments.Add(sHeaderPath, OlAttachmentType.olEmbeddeditem);
var attachLogo = msg.Attachments.Add(sLogoPath, OlAttachmentType.olEmbeddeditem);
attachLogo.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E", "logo");
attachHeader.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E",
"header");
msg.Subject = subject;
msg.To = to;
msg.BodyFormat = OlBodyFormat.olFormatHTML;
msg.HTMLBody = htmlMessage;
//Show email
msg.Display();
//Send email
//((Outlook._MailItem)msg).Send();
oNS.Logoff();
}
catch (Exception ex)
{
Debug.WriteLine("Automate Outlook throws the error: {0}", ex.Message);
}
finally
{
// Manually clean up the explicit unmanaged Outlook COM resources by
// calling Marshal.FinalReleaseComObject on all accessor objects.
// See http://support.microsoft.com/kb/317109.
if (msg != null)
{
Marshal.FinalReleaseComObject(msg);
msg = null;
}
if (oCts != null)
{
Marshal.FinalReleaseComObject(oCts);
oCts = null;
}
if (oCtFolder != null)
{
Marshal.FinalReleaseComObject(oCtFolder);
oCtFolder = null;
}
if (oNS != null)
{
Marshal.FinalReleaseComObject(oNS);
oNS = null;
}
if (oOutlook != null)
{
Marshal.FinalReleaseComObject(oOutlook);
oOutlook = null;
}
}
}
}
}
Example on how to call the class:
var sEmailPath = Path.Combine(Environment.CurrentDirectory, "emails", "single.html");
var htmlMessage = "";
if (File.Exists(sEmailPath))
{
//Load HTML from file
htmlMessage = File.ReadAllText(sEmailPath);
}
Email.SendWithEmbeddedImages("toaddress@test.com", "Outlook Automation Test", htmlMessage);
email.html:
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
</head>
<body>
<table width="600" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td><img src="cid:header"></td>
</tr>
<tr>
<td>
Hello world!
</td>
</tr>
<tr>
<td><img src="cid:logo"></td>
</tr>
</table>
</body>
</html>
Important Notes and Gotchas
- CIDs need to be unique. I’ve seen them on all other posts with the format “file.extension@{random #}” but keeping it simple like in the code above worked for me with no issues with Outlook 2016. I did not test on older versions of Outlook to confirm as I no longer have access to them.
- Outlook ignores font rules in the HTML/CSS you code in the email and defaults to Times New Roman. I know Outlook uses the Word renderer but I have no idea why and the only solution I found was to update the default font in Microsoft Word. Yes, to change the font in Outlook, you’ll need to update the default font in Word. Here’s how to set it:
- Open Word
Go to Options -> Advanced -> Web Options
Change the default font in the Fonts tab
- Open Word
- Outlook only supports a subset of HTML so don’t forget to test and verify everything as most CSS formatting won’t work in Outlook.
Regex to parse date formats when unknown
I’m working on an app that will parse different file sources and aggregate it for a report. Of course, each format has a different date format and trying to parse it all has proved to be a pain. I wrote a regex that’ll parse out just about every datetime format I’ve run into that I am sharing in case someone else finds it useful. I’ve put it on a Github gist along with a sample of the various dates I’ve tested it against and confirmed to work. If you find a format not covered by the regex, post a comment and I’ll update the gist.
Just a note that I haven’t finished parsing the timestamp (e.g. 1997-07-16T19:20:30+01:00) format. The date portion does get extracted correctly so I left it in.
How to Reset Sitecore 7.1 & Sitecore 7.5 Forgotten/Lost Admin Password
In working on implementing a Sitecore site into an existing code base inherited from another vendor, I discovered that the admin password had been modified and the vendor would not share it. Not being able to login to the admin section of Sitecore was not ideal to say the least. After scouring the web, most articles contained instructions on how to reset the password, but almost all of them applied to Sitecore 6 and below. For Sitecore 7 and above, most articles were not applicable as they introduced the PasswordSalt field into the database which Sitecore uses to hash the password.
If you’ve run into a similar situation, or you’ve forgotten or lost your admin account password, getting access back to everything is pretty simple. Load SQL Management (or your favorite SQL editor) and execute this query against your Core database:
UPDATE dbo.aspnet_Membership SET [Password]=’qOvF8m8F2IcWMvfOBjJYHmfLABc=’, [PasswordSalt]=’OM5gu45RQuJ76itRvkSPFw==’, [IsApproved] = ‘1’, [IsLockedOut] = ‘0’ WHERE UserId IN (SELECT UserId FROM dbo.aspnet_Users WHERE UserName = ‘sitecore\Admin’)
This will now reset the default admin password to ‘b’ so that you may login to the Sitecore desktop. Happy editing!
{Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack.}
Problem
If you’re working in ASP.NET and ever ran into the error:
{Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack.}
You’ll probably find that the stack trace gives you no useful information as to where the error actually occurred.
The Solution
For Response.Redirect, use the overload function (Response.Redirect(String url, bool endResponse)) and pass false into the EndResponse parameter:
[csharp]Response.Redirect ("nextpage.aspx", false);[/csharp]
For Response.End, you’ll need to call the HttpContext.Current.ApplicationInstance.CompleteRequest method instead of Response.End to bypass the code execution to the Application_EndRequest event.
Details
The error occurs when you use Response.End, Response.Redirect, or Response.Transfer.The Response.End method ends the page execution and shifts the execution to the Application_EndRequest event in the application’s event pipeline. The line of code that follows Response.End is not executed. This problem occurs in the Response.Redirect and Server.Transfer methods because both methods call Response.End internally.
Detecting ASP.NET debug mode
The Problem
Recently I ran into a situation where I needed to debug ASP.NET code in a production environment that we had no control over. The server was managed by a third party support team and we deployed to a staging environment through a custom web deployment utility they built.
Of course, the code ran locally and on our internal staging environments with no issues but when deployed to the client’s remote staging servers, the application was encountering odd errors that we couldn’t replicate.
At this point, I wanted to add code to the web application that could be turned on and off without having to recompile deploy new dlls because of code changes in the code behind. With this particular client, code changes would trigger security scans that took over a week to complete and we were short on time.
The Solutions that Should’ve Worked but Didn’t.
Page Tracing wasn’t working. I remembered the #if Debug and HttpContext.Current.IsDebuggingEnabled statements worked rather well in other projects.
So I added:
#if Debug //Debug code here #endif
to the web application. Nothing happened so I tried:
if(!HttpContext.Current.IsDebuggingEnabled)
but it kept returning false even though debug mode was set to true in the web.config file.
The Solution (that worked!)
Finally I got the bright idea to read out the debug setting out of the web.config and execute code if the debug flag was set to true. How to do so wasn’t exactly obvious though.
After some searching, I finally figured it out and here’s the code snippet that will execute only if the debug flag is set to true:
System.Web.Configuration.CompilationSection cfg = (System.Web.Configuration.CompilationSection)ConfigurationManager.GetSection("system.web/compilation"); if (cfg.Debug) { Response.Write(ex.ToString()); }
Why Didn’t the Normal Debug Statements Work?
The issue was that the machine was configured as production. The machine.config overrode the web.config since the <deployment retail=”true”/> switch was set in Machine.config.
This setting disables Page.Tracing & #If Debug and always sets the IsDebuggingEnabled to false. This was done by Microsoft as a security precaution for companies so they could ensure no applications were deployed with debugging enabled by mistake.
Bonus! How Do I Loop Through All Session Variables in C#?
I wanted to see what the session variable values were during execution of the page with the caveat that it would only run if the debug flag was set to true.
<% System.Web.Configuration.CompilationSection cfg = (System.Web.Configuration.CompilationSection)ConfigurationManager.GetSection("system.web/compilation"); if (cfg.Debug) { for(int i = 0; i < Session.Contents.Count; i++) { Response.Write(Session.Keys[i] + " - " + Session[i] + "<br />"); } } %>
I added the code directly to the bottom of the aspx page since I didn’t want to modify the code behind and voila! Once the code was added to the page, we found that the expected session variables weren’t populating correctly on the remote server. Unfortunately it required a code change to resolve the issue but I never would have found the cause without the above snippet of code.