Sunday, June 4, 2017

How-To Tail (ColdFusion) Log Files in Windows Command Line via PowerShell and .bat Script

Setting up a new environment, I wanted to tail my coldfusion log files. Usually this is simple in the CFEclipse or CFBuilder log window. Unfortunately, that doesn't work in my new environment (beside the point). So I needed a different solution.... PowerShell to the rescue! It turns out it is super simple to tail files in PowerShell via a command like $ Get-Content coldfusion-out.log -wait. Awesome! But when I save this to a .ps1 file and double-click, it just opens my text editor. How can I double click like a good old .bat file?... well make a a .bat file named the exact same with contents like this:
@ECHO OFF
PowerShell.exe -executionpolicy remotesigned -File %~dpn0.ps1
PAUSE


Now I can double-click my .bat and launch a regular old command window that tails my log file using PowerShell.

In the end, the files look like this:

And the .bat file double-click to command window looks like this:

Rinse and repeat with different log file names for any other log files you want to tail. Of course, this has nothing specifically to do with ColdFusion, but that's what I use it for :-)

Thursday, March 23, 2017

Samsung Gear S2 Won't Turn On - How I fixed it

I was a reluctant buyer of a smartwatch. I got the Gear S2 refurbished a few months ago and I ended up really liking it. Unfortunately, I had one charger die and had to replace it. Otherwise, it has been all good.... until yesterday. I grabbed my watch off the charger and it was dead. It wouldn't even turn on. The charger indicator LED showed blue as if it were charging. I went watch-less for the day. Upon returning home, I tried the following steps which brought my Gear S2 back to life:

  1. Remove any protective backing from the watch (I had a protector skin on it)
  2. Plug the charger into a computer USB (low voltage) port
  3. Place the watch on the charger
  4. Wait 2-3 minutes
  5. The watchface should light up and show that it is charging
  6. Let it fully charge (will take awhile)
  7. Take it off charger and power on
  8. Back to normal! Charge with regular power adapter again as needed
Essentially, my watch refused to charge on the regular power adapter. It would only "trickle-charge" on the lower voltage power source. I think it was in some sort of protective anti-overheating mode as it had been very hot when I pulled it off the charger when it wouldn't power on. The low voltage charge must have been "allowed" by the software whereas the higher voltage charging was being restricted. Just my theory...

Wednesday, March 1, 2017

Prevent Ionic Header from Auto-Scrolling Content to Top when Header is Tapped

An interesting piece of functionality in Ionic that only became aware of today is "tap-scroll" which auto-scrolls to the top of the screen when the header/title of the view is tapped. This only seems to work in iOS and caused some strange behavior in a view that had some custom scrolling related javascript code. This led me to look for ways to disable this cleanly. It turns out there is an attribute available on ion-header-bar called "no-tap-scroll" that can disable this behavior when set to "true".

Take a look at ionic.bundle.js and you'll see this defined for ion-header-bar.


When setting no-tap-scroll="true" on the ion-header-bar element, you'll be able to disable this auto-scroll to top functionality, which I think is rather unexpected behavior.

Synology Cloud Sync with Multiple Folders / Directories

If you have a Synology NAS running DSM, you are likely familiar with the Cloud Sync package. This package has lots of potential, but has one major blocker: each account can only sync one folder. This has supposedly been addressed via "tasks" in newer DSM versions (6+) but if you are stuck on an older version of DSM, you are limited to syncing one folder to the cloud service of choice (i.e. Drive, OneDrive, Amazon, etc). This is problematic if you have a folder structure where folders like Homes, Videos, Music, Photos, etc are all top level shared folders with various permissions. Say you want to back up all Homes and also Videos, Music, and Photos... you must back each one up to a different cloud service. This is a deal breaker. Alternatively, you can move your folder structure around, but that is also a deal breaker if you have multiple users with different permission levels on these folders.

What is the solution for DSM < 6 then? Permanent Symlinks
With permanent symlinks, you can create "virtual" directories that Cloud Sync will see as real directories to include in the sync. This allows you to have something like "\homes\user1\movies" that actually points to "\movies". Granted, your cloud backup folder structure will be different than your actual folder structure, you will at least get everything backed up.

To implement this, there are two steps:

  1. Make the links:
    1. SSH into your Synology
    2. Run "mount -o bind ‹TargetDirectory› ‹VirtualDirectory›"
  2. Make them permanent
    1. Run the link scripts at startup (more info at https://forum.synology.com/enu/viewtopic.php?t=102158)


Saturday, November 12, 2016

Find Your GSM SIM Ready Laptop / Convertible / 2-in-1 / Tablet IMEI

I have been using a Lenovo Thinkpad Helix for months now, successfully replacing 4 towers, 1 laptop, 1 iPad, and 1 Android tablet with the single all-in-one device. It has been great! Now, I am ready to add a GSM SIM card and get this thing fully mobile.

I had no idea what the IMEI is on the device as there is no sticker and I don't have the original box or documentation. After a little searching, I found a handy command that works in Windows command line: '$ netsh mbn show interface'

This produces the following results:


Tuesday, July 12, 2016

How to Convert Apache .htaccess URL Rewrite Rules to IIS web.config

Having put in lots of testing and debugging time, your .htaccess URL rewrites are finally rock solid ( or good enough maybe :-) ). Now you are changing servers from Apache to IIS and you have to come up with all new web.config URL rewrite rules. I've been though this, manually refactoring .htaccess to web.config, and it isn't quick. The good news is that Microsoft has a tool to make this super simple and fast!

First, make sure you have the URL Rewrite module installed in IIS. This is a simple download and install.

Second, open up IIS and go to your website. You should now have a URL Rewrite icon. Double-click on this new icon and you'll see a menu on the right side with an "Import Rules..." option. This is where the magic happens. You can import your .htaccess file or copy/paste the contents and IIS will do the heavy lifting to convert it to web.config.

One thing to note here that could save you some time... the web.config gets generated in the website root. Therefore if your source .htaccess was not in the website root, the generated web.config may need some touch up to the paths. Otherwise, the generated web.config is spot on based on my experience and you are all set!

Reference: https://blogs.msdn.microsoft.com/azureossds/2015/04/23/converting-apache-htaccess-rules-to-iis-web-config-using-iis-manager-for-azure-websites/

Wednesday, July 6, 2016

Creating a PDF on the fly with Ionic/Cordova

So you've got an Ionic app and you need to create PDFs from within the app. You don't want to offload to a server for PDF generation/download because the PDF is user specific and unique each time it is generated, so why not just generated it client side? For one, that was near impossible a number of years ago. Two, you've tried before and it just never worked right. Well, I managed to get PDF generation in an Ionic app and wanted to share my experience so you can do the same.

What we are going to do is capture a portion of the HTML, turn it into a PDF, and trigger the download for the user.

The first step is to add the required libraries:
Cordova Plugins:
"cordova-plugin-file-transfer"
"cordova-plugin-file-opener2"

index.html (install via bower or point to CDN):
<script src="lib/jspdf/dist/jspdf.min.js"></script>
<script src="lib/html2canvas/dist/html2canvas.js"></script>

Next, we create the PDF generation function:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
$scope.generatePDF = function (method) {

       //set the margins for the PDF
 var margins = {
  top: 40,
  left: 40
 };

        // function to create a hidden clone of the target element,
        // allowing manipulation specific for the PDF output without changing the actual target element.
 var hiddenClone = function (element) {
  document.documentElement.style.overflow = 'visible';
  document.body.style.overflow = 'visible';

  // Create clone of element
  var clone = element.cloneNode(true);

  // Position element relatively within the
  // body but still out of the viewport
  var style = clone.style;
  style.position = 'relative';
  style.top = window.innerHeight + 'px';
  style.left = 0;
  style.width = '535px';
  style.zIndex = '9999';

  // Append clone to body and return the clone
  document.body.appendChild(clone);
  return clone;
 }

        // now create the clone of your target element and send it to html2canvas
 var html2Pdf = hiddenClone(document.getElementById('pdfTarget'));
 html2canvas(html2Pdf, {
  onrendered: function (canvas) {
                        // once the canvas is rendered, create new jsPDF object and working variables
   var doc = new jsPDF('p', 'pt', 'letter');
   var dataUrl = canvas.toDataURL('image/jpeg');

   doc.addImage(dataUrl, margins.top, margins.left, canvas.width, canvas.height);
   var dataUrlPdf = doc.output();
   var dataUrlPdfBase64 = 'data:application/pdf;base64,' + btoa(dataUrlPdf);

                        // once we've got the canvas, we can remove the clone element and reset styles
   document.body.removeChild(html2Pdf);
   document.documentElement.style.overflow = 'hidden';
   document.body.style.overflow = 'hidden';

   var filename = 'PDF-' + $filter('date')(new Date(), 'yyyy-M-d') + '.pdf';

   // Save location
   var targetPath = cordova.file.externalRootDirectory + filename;

                        // use the cordova file transfer plugin to send the file to the cordova file opener plugin,
                        // allowing user to pick download method (only seems to work on Android)
   $cordovaFileTransfer.download(dataUrlPdfBase64, targetPath, {}, true).then(function (fileEntry) {
    console.log('Success');
    console.log(fileEntry);
    fileEntry.file(function (file) {
     cordova.plugins.fileOpener2.open(
      file.localURL,
      file.type, {
       error: function (e) {
        console.log('Error status: ' + e.status + ' - Error message: ' + e.message);
       },
       success: function () {
        console.log('file opened successfully');
       }
      }
     );
    });
   }, function (error) {
    console.log('Error');
    console.log(error);
   }, function (progress) {
    // PROGRESS HANDLING GOES HERE
   });
  }
 });
};

Now you can run the function and try it out...
Hopefully you'll have successful client side PDF generation from HTML. I will say these plugins/libraries are touchy, especially when used together but this formula worked for me. Best of luck and feel free to share your implementations and feedback!