Encoding .NET bitmaps to H264 using FFMPEG
2016-11-28
Recently, I was working on a project that involves the encoding of .NET bitmaps using ffmpeg’s h264 encoder with mp4 as container. This video output will be used in a <video> tag in html5. Sample codes have been all over the place so it took me quite a while to come up with a working solution. The official sample from ffmpeg only encodes to raw h264 stream. This is just a basic sample code for reference.
1 minute
A simple cron-like Windows service
2016-10-07
A couple of days ago, I uploaded a generic service in GitHub that has a feature of updating itself. Check out the post here. Today, I uploaded the actual service I’m using in our CI environment, excluding the configuration file. Check out the source code here.
1 minute
A Windows service with an http endpoint for uploading a new version of itself
2016-09-27
Recently, I’ve been working on a service that runs on a lot of VM’s across different locations. If I have a new service build, updating all of the running instances quickly became a bit of a pain. I have to log in to every VM (in some cases through a VPN) and then do a manual upgrade. Now, there are probably tools that already exist for this type of use case but since I’m still learning Go at the moment, I thought this would be a good exercise.
1 minute
A simple REST client/server console app in C#
2016-08-24
For personal reference: Full source code here.
1 minute
2016-08-22
For personal reference: To view syslog in realtime tail -f /var/log/syslog
1 minute
How to serve expvar when using gorilla/mux
2016-08-20
For personal reference: Access root http://localhost:8000 Access expvar information http://localhost:8000/debug/vars
1 minute
My commonly used commands in GIT
2016-08-18
Update 2017/03/24: Transferred to a separate repository here. For personal reference: Reset a file git checkout HEAD -- my-file.txt Delete last commit git reset --hard HEAD~1 Delete local branch git branch -d <branch-name> or to force delete git branch -D <branch-name> Delete branch from remote repository git push origin --delete <remote-branch-name> Search for the merge commit from a specific commit git log <SHA>..master --ancestry-path --merges Search for a commit message git log | grep <pattern> List commits on range line of codes for one file git blame -L<line#>,+<offset> -- <filename> For example, three lines starting from line 257 of main.cpp
2 minutes
2016-08-11
I use tmux heavily and in tandem with vim. Much more so now when it’s supported on Bash on Windows as well. I don’t have to spin up a Linux VM just for the purpose of being my tmux “server”. # Set a Ctrl-b shortcut for reloading tmux config unbind r bind r source-file ~/.tmux.conf Prefix is Ctrl-a unbind C-b set -g prefix C-a bind C-a send-prefix Rename terminals set -g set-titles on set -g set-titles-string '#(whoami)@#h@#(curl ipecho.net/plain;echo)' Status bar customization set -g status-bg black set -g status-fg white set -g status-interval 5 set -g status-left-length 90 set -g status-right-length 60 set -g status-left "#[fg=Green]#(whoami)#[fg=white]@#[fg=red]#(hostname -s)#[fg=white]|#[fg=yellow]#(curl ipecho.net/plain;echo)#[fg=white]|#[fg=yellow]#(hostname -I)#[fg=white]" set -g status-justify left set -g status-right '#[fg=Cyan]#S #[fg=white]%a %d %b %R' Easy to remember split pane commands bind | split-window -h bind - split-window -v unbind '"' unbind % Vim friendly settings (from https://gist.github.com/anonymous/6bebae3eb9f7b972e6f0) setw -g monitor-activity on set -g visual-activity on set -g mode-keys vi Extend history limit set -g history-limit 10000
1 minute
2016-07-27
Vim has always been my go to editor/IDE when I’m outside of Visual Studio. Here’s my base _vimrc for Windows. let mapleader = " " filetype off syntax on colorscheme darkblue " let pc=$PC " if pc == 'HOME' " set guifont=Letter\ Gothic\ Std:h11 " else " set guifont=Lucida\ Sans\ Typewriter:h9 " endif " Save marks to up to 100 files, save global marks as well (f1). To disable, f0 set viminfo='100,f1 " Folding options set foldmethod=indent set foldnestmax=20 set nofoldenable set foldlevel=0 set guifont=Lucida\ Sans\ Typewriter set lines=70 columns=160 set ai set nu set tabstop=4 set shiftwidth=4 set softtabstop=4 set expandtab set wrap set backspace=2 set encoding=utf-8 set fileencodings=utf-8 set nocompatible set noswapfile set shortmess+=I set ignorecase set guioptions-=T set guioptions-=r set guioptions-=m set splitright set splitbelow set ruler set rtp+=$HOME/vimfiles/bundle/Vundle.vim/ call vundle#begin('$USERPROFILE/vimfiles/bundle/') Plugin 'VundleVim/Vundle.vim' " 1. Vim should be 64-bit (link in ycm site) " 2. Python should be 64-bit Plugin 'Valloric/YouCompleteMe' Plugin 'fatih/vim-go' Plugin 'PProvost/vim-ps1' call vundle#end() filetype plugin indent on " To ignore plugin indent changes, instead use: " filetype plugin on " let g:netrw_liststyle=3 let g:ycm_disable_for_files_larger_than_kb = 0 let g:ycm_autoclose_preview_window_after_completion = 1 " Enable powershell syntax plug autocmd BufNewFile,BufReadPost *.ps1 set filetype=ps1 " Search for the word under cursor in the current dir (recursively) command CSM :execute "vimgrep /" . expand("<cword>") . "/j ** <Bar> :cw" nnoremap <leader>ms :CSM<CR> " Simple mappings for window manipulations nnoremap <leader>wq <C-W>q nnoremap <leader>ws <C-W>s nnoremap <leader>wv <C-W>v nnoremap <leader><left><left> <C-W><left> nnoremap <leader><right><right> <C-W><right> nnoremap <leader><up><up> <C-W><up> nnoremap <leader><down><down> <C-W><down> " Display buffers, then prep the colon for the next command nnoremap <leader>b :ls<CR>: " Shortcut for save nnoremap <leader>s :w<CR> " Shortcut for netrw explorer nnoremap <leader>e :e.<CR> " JSON pretty print (all buffer) nnoremap <leader>pj :%!python -m json.tool<CR> " Diff all windows (should prep 2 windows for this) nnoremap <leader>dt :windo diffthis<CR> nnoremap <leader>do :windo diffoff!<CR> {% endhighlight %} And here's my base .vimrc for Linux and OSX. {% highlight conf %} let mapleader = " " filetype off syntax on colorscheme elflord set rtp+=~/.vim/bundle/Vundle.vim call vundle#begin() Plugin 'VundleVim/Vundle.vim' Plugin 'Valloric/YouCompleteMe' Plugin 'jelera/vim-javascript-syntax' Plugin 'fatih/vim-go' Plugin 'majutsushi/tagbar' call vundle#end() filetype plugin indent on " Save marks to up to 100 files, save global marks as well (f1). To disable, f0 set viminfo='100,f1 " Folding options set foldmethod=indent set foldnestmax=20 set nofoldenable set foldlevel=0 set tabstop=4 set shiftwidth=4 set softtabstop=4 set expandtab set autoindent set nu set encoding=utf-8 set noswapfile set shortmess+=I set backspace=2 set nocompatible set ignorecase set splitright set splitbelow set ruler " Temporary enable/disable YouCompleteMe. Active = disable, commented = enable " let g:loaded_youcompleteme = 1 let g:ycm_global_ycm_extra_conf = "~/.ycm_extra_conf.py" let g:ycm_disable_for_files_larger_than_kb = 0 let g:ycm_autoclose_preview_window_after_completion = 1 " Options for netrw let g:netrw_liststyle = 0 let g:netrw_altv = 1 " 1. :PluginInstall " 2. :GoInstallBinaries (gotags, vim-go) " 3. Install 'ctags' " 4. go get -u github.com/jstemmer/gotags let g:tagbar_type_go = { \ 'ctagstype' : 'go', \ 'kinds' : [ \ 'p:package', \ 'i:imports:1', \ 'c:constants', \ 'v:variables', \ 't:types', \ 'n:interfaces', \ 'w:fields', \ 'e:embedded', \ 'm:methods', \ 'r:constructor', \ 'f:functions' \ ], \ 'sro' : '.', \ 'kind2scope' : { \ 't' : 'ctype', \ 'n' : 'ntype' \ }, \ 'scope2kind' : { \ 'ctype' : 't', \ 'ntype' : 'n' \ }, \ 'ctagsbin' : 'gotags', \ 'ctagsargs' : '-sort -silent' \ } nnoremap <F8> :TagbarToggle<CR> " Search for the word under cursor in the current dir (recursively) command CSM execute ":vimgrep /" . expand("<cword>") . "/j ** <Bar> :cw" nnoremap <leader>ms :CSM<CR> set wildignore+=jennah " Simple mappings for window manipulations nnoremap <leader>wq <C-W>q nnoremap <leader>ws <C-W>s nnoremap <leader>wv <C-W>v nnoremap <leader><left><left> <C-W><left> nnoremap <leader><right><right> <C-W><right> nnoremap <leader><up><up> <C-W><up> nnoremap <leader><down><down> <C-W><down> " Display buffers, then prep the colon for the next command nnoremap <leader>b :ls<CR>: " Shortcut for save nnoremap <leader>s :w<CR> " Shortcut for netrw explorer nnoremap <leader>e :e.<CR> " JSON pretty print (all buffer) nnoremap <leader>pj :%!python -m json.tool<CR> " Diff all windows (should prep 2 windows for this) nnoremap <leader>dt :windo diffthis<CR> nnoremap <leader>do :windo diffoff!<CR> " Highlight/no highlight for search nnoremap <leader>hl :set hlsearch<CR> nnoremap <leader>hn :set nohlsearch<CR> " Diff all windows (should prep two windows for this) nnoremap <leader>dt :windo diffthis<CR> nnoremap <leader>do :windo diffoff!<CR> Update (2016/08/24) Updated vimrc can be viewed here.
4 minutes
A simple Powershell function to import an environment
2016-05-06
A couple of days ago, I was working on a powershell-based script for mstest automation and I needed to call vsdevcmd.bat from Visual Studio’s tools folder. function Invoke-Environment([Parameter(Mandatory=1)][string]$Command, [switch]$Output, [switch]$Force) { $stream = if ($Output) { ($temp = [IO.Path]::GetTempFileName()) } else { 'nul' } $operator = if ($Force) {'&'} else {'&&'} foreach($_ in cmd /c " $Command > `"$stream`" 2>&1 $operator SET") { if ($_ -match '^([^=]+)=(.*)') { [System.Environment]::SetEnvironmentVariable($matches[1], $matches[2]) } } if ($Output) { Get-Content -LiteralPath $temp Remove-Item -LiteralPath $temp } } To use the function: Invoke-Environment '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\VsDevCmd.bat"'
1 minute
A simple unzip function in Powershell
2016-04-06
function UnzipFiles($ZipFileName, $DestDir) { Add-Type -Assembly System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::ExtractToDirectory($ZipFileName, $DestDir) } To use the function: UnzipFiles -ZipFileName .\folder\file.zip -DestDir .\destination
1 minute
A simple zip function in Powershell
2016-04-05
function ZipFiles($ZipFileName, $SourceDir) { Add-Type -Assembly System.IO.Compression.FileSystem $compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal [System.IO.Compression.ZipFile]::CreateFromDirectory($SourceDir, $ZipFileName, $compressionLevel, $false) } To use the function: ZipFiles -ZipFileName test.zip -SourceDir .\folder\to\zip
1 minute
[Part 6] Logging with Universal Apps
2016-03-22
Check out the codes in GitHub. Basically, 2 steps: Create a C++ Windows Runtime Component (dll) that will use the ETW header file. Reference the WinRT DLL to C# project. WinRT DLL My logging class looks like this: public ref class TraceCore sealed { private: TraceCore(); ~TraceCore(); static TraceCore^ m_Instance; public: static property TraceCore^ Instance { TraceCore^ get() { if (m_Instance == nullptr) { m_Instance = ref new TraceCore(); } return m_Instance; } } void Verbose(Platform::String^ mod, Platform::String^ file, Platform::String^ func, Platform::String^ m); }; And heres the implementation: #include "pch.h" #include "TraceCore.h" using namespace LibRTWrapperETW; using namespace Platform; #include "jytrace.h" TraceCore^ TraceCore::m_Instance = nullptr; TraceCore::TraceCore() { EventRegisterJyTrace(); } TraceCore::~TraceCore() { EventUnregisterJyTrace(); } void TraceCore::Verbose(String^ mod, String^ file, String^ func, String^ m) { EventWriteSimple(mod->Data(), file->Data(), func->Data(), L"Trace", m->Data()); } Wrapper Class Just like in part 5, I wrapped the C++ bits to a C# class so I can use the CallerMemberName and CallerFilePath attributes:
1 minute
[Part 5] Logging with C# applications
2016-03-19
Check out the codes in GitHub. I generated a C# logging class using this command: mc -css <Namespace_here> jytrace.man So far, most of my event templates use an ANSI string data type which (I believe) is not supported by C#. As you can see in part 1, I use ANSI data type for my File and Function fields so that I can use __FILE__ and __FUNCTION__ as inputs in C++. Thats why I added a new event template with all fields using UNICODE data types. Again, you can refer to the whole package here for reference.
1 minute
2016-03-07
Check out the codes in GitHub. Getting the logs Now that I have my modules spitting out logs for me, it’s time to actually consume (or view) them. Most of the time, I use MFTrace and logman tools. MFTrace Although MFTrace is primarily a tool for generating logs for Media Foundation apps, it is a great tool for viewing ETW logs in general as well. It is included in the MS SDK.
2 minutes
[Part 3] Logging with C/C++ applications
2016-03-03
Check out the codes in GitHub. If you remember in part 2, we compiled our manifest file with mc -um <manifest_file>.man and we got a header file as one of the outputs. We just have to include that header file to our sources and we are good to go. #include ... #include "<manifest_file>.h" int main(...) { EventRegister<provider_name_in_manifest>(); ... CreateFile(...); // Example of using the LastError event in our manifest file EventWriteLastError(L"THIS_EXE", __FILE__, __FUNC__, L"CreateFile", GetLastError()); ... EventUnregister<provider_name_in_manifest>(); } Notes
1 minute
[Part 2] Manifest file compilation and setup
2016-03-02
Check out the codes in GitHub. Compiling the manifest file This is how I compiled my manifest file. Open Visual Studio command prompt. Compile manifest file. mc -um <manifest_file>.man When successful, output files are: <filename>.h <filename>.rc <filename>TEMP.BIN MSG00001.bin Creating the message resource DLL I like to create a separate dll just for the manifest file resource although you can also add the .rc file to any of your existing dll or exe.
1 minute
[Part 1] How I set up ETW for logging (native, .NET, Metro and UApp)
2016-03-01
Check out the codes in GitHub. Ive been using ETW as my go-to logging mechanism for Windows development. I will be sharing how I setup my environment here. Creating the manifest file (.man) I use ecmangen.exe to create my manifest file. This tool is included in the SDK. I have Visual Studio 2015 installed on a Win10 64-bit machine, and its location is C:\Program Files (x86)\Windows Kits\10\bin\x64\. It looks something like this (my completed manifest):
3 minutes