This is just to inform that I got the C# #Csharp gold badge at #StackOverflow @StackExchange after 5 years and 6 months and 342 answers posted on the C# tag! What a milestone towards a so awesome programming language.
Once when I was starting back in 2003 a somewhat experienced coworker told me: this thing [ coding ] is not for you.
I proved him wrong!
The lesson to be learnt here is: never trust others when they say you are not capable even more when you are just starting something. Instead use that as a trampoline. Not easy but you must not give up. Keep pushing always.
People that motivate us are a rare kind. So use this post as a motivation and BEFORE that remember: put God first in everything you start in your life. I remember at that time in my life I talked to God and told him that I really liked this profession|area and asked for his help so that he could guide me and provide me wisdom. Here I’m today being able to write this post. How grateful I’m.
To top that, last week a cousin (13 years old) approached me and told me he’d like to follow the same path I followed and asked what I did to get where I’m today. I answered: you have to have a passion for what you do, strive for excellence and be prepared to spend some good amount of time trying and trying... as I wrote above: don’t give up. There’ll be for sure many rocks on the road… The Long and Winding Road as sung by The Beatles is a truth but if you persist in what you really believe then success is a matter of time.
Somehow sometime somewhere God will move things in your favor.
And we know that all things work together for good to them that love God, to them who are called according to his purpose. Romans 8:28 https://www.bible.com/bible/1/rom.8.28
NPOI has got you covered too. The flag first appeared in NPOI 2.0 Alpha:
g. Support isRightToLeft and setRightToLeft on the common spreadsheet Sheet interface, as per existing HSSF support (poi-developers)
Let’s jump directly to the code with no further ado…
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System.IO;
namespace NPOI.Examples.XSSF.SetIsRightToLeftInXlsx
{
class Program
{
static void Main(string[] args)
{
IWorkbook workbook = new XSSFWorkbook();
ISheet sheet1 = workbook.CreateSheet("Sheet1");
// Setting support for Right To Left
sheet1.IsRightToLeft = true;
sheet1.CreateRow(0).CreateCell(0).SetCellValue("This is a Sample");
int x = 1;
for(int i = 1; i <= 15; i++)
{
IRow row = sheet1.CreateRow(i);
for(int j = 0; j < 15; j++)
{
row.CreateCell(j).SetCellValue(x++);
}
}
FileStream sw = File.Create("test.xlsx");
workbook.Write(sw);
sw.Close();
}
}
}
You can find the above code in the SetIsRightToLeftInXlsx sample project. I sent a pull request to Tony Qu so that this sample project gets added to NPOI’s GitHub repository.
I’m going to share here a pretty nice deployment automation solution for when you need to have a defined set of folders in place when first deploying an app to IIS. On subsequent re-deployments the folder structure will be kept intact with any files users may have added to them.
Let’s work with a simple example: given an ASP.NET MVC app, we need a folder called Files and inside this folder there will be some pre-defined folders named: Folder 1, Folder 2 and Folder 3 with a child folder called Test. Something like this:
When deploying for the 1st time these folders are empty but the folder structure is mandatory let’s say because I’m using a file manager like elFinder.Net that expects that these folders exist on the server. Why? Because the ASP.NET MVC app has links pointing to these folders in some views. The folders should be ready to store files when the app is released. What also comes to my mind is the case where we need an existing Downloads/Uploads folder.
What’s more? We also want all this to happen while using Publish Web command from within Visual Studio and still keeping the option Remove additional files at destination checked:
Figure 1 - Visual Studio Publish Web with File Publish Options => Remove additional files at destination
This setting is nice because when you update jQuery NuGet package for example (jquery-2.1.1.js) it will send the new files to IIS server and will remove the old version (jquery-2.1.0.js) that exists there. This is really important so that the app keeps working as expected and don’t load the wrong version/duplicate files. If we don’t check that option we have to go to the server and delete the old files manually. What a cumbersome and error prone task!
What to do in this case where we want the deployment task do the work “automagically” for us with no human intervention? It’s seems like a lot of requirements and a task not so simple as “it appears to be”… Yep, it requires a little bit of MsDeploy codez.
Here’s what is working for me at the moment after finding some code pieces from here and there:
Given a publish profile named Local.pubxml that sits here: C:\Company\Company.ProjectName\Company.ProjectName.Web\Properties\ PublishProfiles\Local.pubxml
Let’s add the code blocks necessary to make all the requirements come to life:
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit http://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AfterAddIisSettingAndFileContentsToSourceManifest>AddCustomSkipRules</AfterAddIisSettingAndFileContentsToSourceManifest>
<WebPublishMethod>MSDeploy</WebPublishMethod>
<LastUsedBuildConfiguration>Local</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<ExcludeApp_Data>False</ExcludeApp_Data>
<MSDeployServiceURL>localhost</MSDeployServiceURL>
<DeployIisAppPath>SuperCoolAwesomeAppName</DeployIisAppPath>
<RemoteSitePhysicalPath />
<SkipExtraFilesOnServer>False</SkipExtraFilesOnServer> <MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
<AllowUntrustedCertificate>True</AllowUntrustedCertificate> <EnableMSDeployBackup>False</EnableMSDeployBackup>
<UserName />
<_SavePWD>False</_SavePWD>
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
</PropertyGroup>
<PropertyGroup>
<UseMsDeployExe>true</UseMsDeployExe>
</PropertyGroup>
<Target Name="CreateEmptyFolders">
<Message Text="Adding empty folders to Files" />
<MakeDir Directories="$(_MSDeployDirPath_FullPath)\Files\Folder 1" />
<MakeDir Directories="$(_MSDeployDirPath_FullPath)\Files\Folder 2" />
<MakeDir Directories="$(_MSDeployDirPath_FullPath)\Files\Folder 3\Test"/>
</Target>
<Target Name="AddCustomSkipRules" DependsOnTargets="CreateEmptyFolders">
<Message Text="Adding Custom Skip Rules" />
<ItemGroup>
CreateEmptyFolders take care of adding/creating the folder structure on the server if it doen’t exist yet.
AddCustomSkipRules contains two <MsDeploySkipRules...>. One is to prevent deleting Files and the other prevents deleting the child folders.
Check the targets’ logic. They’re pretty easy to understand…
Note: make sure you don’t forget the
<UseMsDeployExe>true</UseMsDeployExe>
otherwise you may see this error during deployment:
Error 4 Web deployment task failed. (Unrecognized skip directive 'skipaction'. Must be one of the following: "objectName," "keyAttribute," "absolutePath," "xPath," "attributes.<name>.") 0 0 Company.ProjectName.Web
Simple as pie after we see it working. Isn’t it?
Hope it helps!
As an interesting point, see the command executed by msdeploy.exe that gets written to the output window in Visual Studio:
Today I sent a small pull-request to the awesome Font-Awesome project at GitHub. To do that I had to learn some bits along the way that diverted from the common path when working with GitHub.
Font-Awesome has a separate branch called gh-pages which hosts the GitHub Pages (site) for Font-Awesome. The change I was about to do should go inside that branch and not on the common master branch.
Generally when cloning a forked repo from GitHub it will bring/checkout only the master branch.
Problem: how can I do work on that gh-pages branch?
This is the solution that worked just fine in my case…
Take a look at the following screenshot:
Figure 1 - Checkout remote branch (not master) named gh-pages to a local branch with upstream tracking
Above I have Git bash (you can get it here) opened in the cloned repo folder. I used GitHub for Windows to clone the repo I forked from Font-Awesome.
When you open Git bash it has the (master) branch already checked out as you see in “yellow” above.
Executing the command:
git remote show origin
we see that the repo has 3 Remote branches, namely:
4.1.0-wip gh-pages master
however only the master branch is configured for git pull and git push on my local computer. That’s ok if I would do some work on the master branch. If that was the case I already had everything correctly setup but remember that I need to do work on the gh-pages branch. To do so, the following command must be executed:
git checkout –b gh-pages –-track origin/gh-pages
What this command does is:
With git checkout we create a new local branch called gh-pages and immediately switch to it with the –b parameter. See that the branch name matches the one from the remote origin, in this case, gh-pages.
The –-track parameter means that this new local branch has its upstream set to a remote branch, in this case origin/gh-pages.
This is the result I wanted.
As a visual clue, in the following screenshot you see that the branch now shows in Visual Studio 2013Team Explorer window as the selected one. This means it made it to my local computer. Now I can work on it and when done I can click on that Changes link and push my changes to the remote origin.
Figure 2 - gh-pages branch appears in Published Branches in Visual Studio 2013 Team Explorer window
To prepare for working on <branch>, switch to it by updating the index and the files in the working tree, and by pointing HEAD at the branch. Local modifications to the files in the working tree are kept, so that they can be committed to the <branch>.
If <branch> is not found but there does exist a tracking branch in exactly one remote (call it <remote>) with a matching name, treat as equivalent to
You could omit <branch>, in which case the command degenerates to "check out the current branch", which is a glorified no-op with a rather expensive side-effects to show only the tracking information, if exists, for the current branch.
I should have submitted the pull request against the 4.1.0-wip branch where wip means (work in progress).
OK… I went further and did all the process again (a brand new pull request) but this time targeting the correct branch. I even learned a new thing using Git Gui (installed with Git tools):
Figure 3 - Creating a tracking branch with Git Gui with the same name [ 4.1.0-wip ] as defined in origin
To get to Git Gui, right click the repo folder on the disk and select Git Gui in the context menu.
To create a new branch, click the Branch menu then Create…
See that I selected Match Tracking Branch Name and made Tracking Branch point to origin/4.1.0-wip. Then clicked the Create button.
What this does is the same thing achieved with that previous Git checkout command executed above. The only difference is that now it’s all visual.
It’s real nice to have options to get the job done.
Inside this folder there’s an SQLite database file called main.db (mine is 13.1 MB) with all chat history. For more details on that, check this answer on SuperUser:
I got the MacDropAny 2.12.zip zip package and extracted the .app. Moved it to Mac OS Applications folder and opened it.
It asks you to choose a folder to sync with the cloud. I wanted to select that Skype chat history folder described above. Problem: that folder is stored inside the Library folder that is hidden by default in Mac OS and so it won’t show up in the list of folders available to MacDropAny. To fix that, follow what’s described here. Open Mac OS Terminal and type:
chflags nohidden ~/Library/
Now when asked to Choose a folder, Library will be available:
Figure 1 - Select Skype user folder (lenielmacaferi) to be backed up to the cloud
After clicking Choose we need to select the Cloud service provider where to store the files:
Figure 2 - Selecting cloud service provider
Then it’s necessary to choose where to store the files in Google Drive. I created a new folder there called Skype and selected it:
Figure 3 - Choose an existing folder (Skype) on Google Drive or create New Folder
It then allows you to give a different name to the folder to be backed up. I kept the same name and clicked Sync.
Figure 4 - Name the folder copy (I kept the same)
You may be prompted to enter your password to allow MacDropAny to access the Library folder. Provide the password if asked and you’re done.
Figure 5 - MacDropAny Folder Sync Success message
This is the cloud’s power at its best.
Now I have a security copy of all my Skype history in a “safe” place.
This is a lengthy post for something I think is really worthwhile. If you’re into code exploration read on…
Last week I got frustrated while looking for a simple app that could alert me from time to time that I should get up and move/take a break instead of sitting during work hours for more than 1 | 2 | 3 | 4 | ? hours. You know…software people tend to pass maybe 1/4 of their lives stationary in a chair. That’s too much time if we think about it.
Here’s my tweet:
Got tired of looking for an #Alarm app for #Mac and decided to go with #Windows 8 Alarms app. The only problem is the lack of Hourly option.
Yes, Mac OS has an option to announce the time on Date & Time preferences (Clock tab). A robot voice can speak the time on the quarter hour, on the half hour and on the hour but it’s very limiting (lack configuration options). It wasn’t what I was looking for…
I then tried Mac OS Calendar app with its built-in alerts but it’s not the right tool for the job.
So I thought, let me go to Windows 8 side. I use Parallels Desktop 9 for Mac and so both operating systems live side by side in perfect harmony. With a Window 8 Parallels Virtual Machine I can switch from Mac OS Mavericks to Windows 8 and vice-versa with a 4 finger swipe gesture in the MacBook magic trackpad. This is real good. If you don’t know Parallels Desktop for Mac I highly recommend you go take a look at it.
On the Windows 8 side I just stumbled on the Alarms metro app and I really liked it.
Figure 1 - Nice looking/modern and to the point Windows 8 Alarms metro app
It has a pretty beautiful and well thought/modern UI and the Win 8 “toast” alert notification is really cool and guess what: the notifications raised in Windows also show as Mac OS Notifications1 thanks to Parallels for Mac integration. Besides that, the notifications are shown just while you’re working/while the PC is awake. This is really what I was looking for…
Using the Alarms app you can configure the alarm repeat frequency and select a sound (the available sounds really nice too). One downside is that as of now (Windows 8.1) it doesn’t have an option to set an hourly alarm. I suggested it to the Win team. Lacking the hourly option I started creating alarms like crazy let’s say from 30 in 30 minutes just to find another limitation: the Alarms app allows only 20 alarms. I tried to cheat it looking at the Alarms.json file used to persist the alarms data. The file is saved here:
but adding a new alarm by hand in this JSON file had no effect when reopening the Alarms app. I think the app code limits the alarms when parsing this file.
Of course I could set the alarms with a minor frequency like from 1 to 1 hour (what I did and that works beautifully). As a coder and explorer I started looking for some code that would allow me to overcome the manual alarms creation/configuration and the 20 alarms limit – read Automate the whole process.
I found Alarm toast notifications sample on Windows Dev Center. With the code in hands I could play with it and understand how Windows 8 does those pretty looking “toast” notifications. This was also a great opportunity to learn a little bit about Win 8 app development since I had never played with it. I’m more a web guy doing lots of ASP.NET webstack of love development these days.
I got the .zip file with C# code and fired our dear Visual Studio 2013. I was prompted to get a developer certificate and then the solution loaded without a glitch and compiled just fine. Went through the code and what I can say is that: win development (WPF/XAML) and desktop dev in general is really not as cool as doing web ASP.NET dev – this is just my humble opinion though. Lots and lots of code just to manage guess what WINDOWS. XAML designer is a heavy weight guy and takes seconds to load even on a powerful machine. Despite this, the code is easy to understand if you’ve done something as Win Forms dev.
The sample app has basically a window with 2 buttons. When clicking the first button it dispatches a notification toast to Win 8. The are plenty of options regarding the toast alert notification but I’m only interested in simulating the click of the Default Snooze button.
Figure 2 - Alarm Notifications C# Sample app main window
I started with this idea: I want to get this app notification fired with Windows Task Scheduler. Task Scheduler is such a powerful tool in Windows and allows for a great range of configuration.
To that end I created a Task that calls the win 8 sample app from time to time, say from 1 in 1 hour (just like my original alarms idea) or from 50 in 50 minutes or any interval desired.
First attempt to see if/how this could work was: right-clicked the AlarmNotifications project in Visual Studio and selected Store => Create App Packages and then Visual Studio built a local package that got saved to
I promptly installed it running the PowerShell script provided - it’s called Add-AppDevPackage.ps1.
Figure 3 - Installing the App package with PowerShell script
After installation the app called Alarm Notifications C# could be opened in Win 8 Apps. Worked perfectly.
Note: One thing I’ve learnt is that there’s no need to package and install the app manually. You can just deploy it using Visual Studio’s green/play button to Run in Local Machine. This is way better because doing it from inside Visual Studio you can change the app code and redeploy immediately with the click of that button.
Now the question is how to open this app using Task Scheduler? This is a good question!
First blocker: Win 8 metro apps cannot be opened directly. Win 8 apps are installed in this folder:
Oh oh… this is bad. Sure. So how can the app be opened with Task Scheduler help? Aha… 2nd good question. Googling for that and there’s a way around it called Protocol Activation. Basically you register a protocol in the project’s Package.appxmanifest file in Visual Studio like this:
Figure 4 - Defining the app Protocol that will be used as the Start Program argument in Task Scheduler
The protocol I registered for the sample app was toast. Doing this now I’m able to launch the app using Task Scheduler with this command:
Explorer toast:
This is cool man! We just overcame Win 8 metro apps .exe limitation.
Now that a protocol was defined for the app, a small piece of code is necessary and goes into the App.xaml.cs code behind:
protected override void OnActivated(IActivatedEventArgs args)
{
if(args.Kind == ActivationKind.Protocol)
{
ProtocolActivatedEventArgs protocolArgs = args as ProtocolActivatedEventArgs;
var rootFrame = new Frame();
rootFrame.Navigate(typeof(MainPage), args);
Window.Current.Content = rootFrame;
}
Window.Current.Activate();
}
This code watches over how the app was activated… in this specific case it checks for the Protocol activation method.
With this in place we can pass the ball to Task Scheduler.
Here’s the Task Scheduler task action:
Figure 5 - Task Scheduler Task’s Action explorer toast:
The trigger:
Figure 6 - Task Scheduler Task’s Trigger At Startup and repeat indefinitely every 1 minute
Note that for testing I set the task to repeat every 1 minute. This is the part you should change let’s say from 1 to 1 hour.
I exported this task’s XML and put it in this repo at GitHub. If you wish you can import this task in your Windows Task Scheduler.
You can play with the task’s schedule the way you want. There are plenty of configuration options available.
OK. Now the foundation is laid but there’s yet one blocker to overcome. The sample app has a window called MainPage and this window has 2 buttons as seen in Figure 2. The alarm notification will only be triggered when clicking the Default Snooze button in that window. So no matter if Task Scheduler opens the app, the alarm notification will never appear. What I’m doing is an automated process and so somehow that button must be clicked in the code. What to do in this case? It’s simple: simulate the button click programmatically. Let me Google for it. The answer is here:
The next thing to do is to find in the sample app’s code where that code should go. I put it in the Toast.xaml.cs code behind file in the ToastScenario constructor:
public ToastScenario()
{
this.InitializeComponent();
// Let's call the XAML button click programmatically
ButtonAutomationPeer peer = new ButtonAutomationPeer(DefaultSnooze);
IInvokeProvider invokeProv = peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
invokeProv.Invoke();
}
This did the trick!
I also changed the click even handler a little bit:
private void SendToast_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
if(b != null)
{
// Get some data from the button the user clicked on.
string toastTemplate = b.Name;
string alarmName = "";
if(toastTemplate.Contains("Custom"))
{
alarmName = "This will make you fell better. Snooze me if you want...";
}
else
{
alarmName = "This will make you fell better. Snooze me if you want...";
}
// Create the toast content by direct string manipulation.
// See the Toasts SDK Sample for other ways of generating toasts.
string toastXmlString =
"<toast duration=\"long\">\n" +
"<visual>\n" +
"<binding template=\"ToastText02\">\n" +
"<text id=\"1\">Get Up and Move coder!</text>\n" +
"<text id=\"2\">" + alarmName + "</text>\n" +
"</binding>\n" +
"</visual>\n" +
"<commands scenario=\"alarm\">\n" +
"<command id=\"snooze\"/>\n" +
"<command id=\"dismiss\"/>\n" +
"</commands>\n" +
"<audio src=\"ms-winsoundevent:Notification.Looping.Alarm2\" loop=\"true\" />\n" +
"</toast>\n";
// Display the generated XML for demonstration purposes.
rootPage.NotifyUser(toastXmlString, NotifyType.StatusMessage);
// Create an XML document from the XML.
var toastXML = new XmlDocument();
toastXML.LoadXml(toastXmlString);
// Create the toast and attach event listeners
ToastNotification toast = new ToastNotification(toastXML);
//toast.Activated += ToastActivated;
//toast.Dismissed += ToastDismissed;
//toast.Failed += ToastFailed;
// Show the toast. Be sure to specify the AppUserModelId on your application's shortcut!
ToastNotificationManager.CreateToastNotifier().Show(toast);
// Exit the app after dispatching the toast
Application.Current.Exit();
}
}
It dispatches the notification immediately and closes the Application after that.
Once the toast notification appears one must take action: click the small X icon or click dismiss to make the notification go away. Of course after doing this you should actually Get Up and Move/exercise for some time. Why not go get some water or even coffee?
Figure 7 - Customized Windows 8 Toast Notification
Here’s a YouTube video where I demo the app running with the help of Task Scheduler:
You can see the toast notification appear right after I run the Task Scheduler task. See how beautiful it is an how catching is the sound. By the way, the sound can be changed too editing the <audio> tag in the toast XML template in Toast.xaml.cs:
One interesting thing is that If the toast is not closed/dismissed the sound gets louder and louder…
Let’s get up and move because back pain is back pain and sitting all day long can put you in trouble.
Hope you liked this code exploration.
1 to get the alert notification on the Mac OS side, the modified sample app must be opened and present in the Mac OS dock; otherwise the notification can only be seen in the Windows side. This is a Parallels for Mac limitation and I hope in the future they also make it possible to show notifications from windows metro apps that are running in the background. The nice thing is that the alarm sound still plays while on the Mac OS side.
Get the codez
The modified source code is available at this GitHub repo: