Windows 10 | Windows cannot connect to the printer

There are times when you come across the error “Windows cannot connect to the printer” (error 0x000003e3) while trying to connect to a shared printer that is connected to another Windows 10 computer.

Quite possible that the drivers installed on the source machine is either not compatible with the client/target machine or not getting copied to the target machine. Now, install the correct version of printer driver to the target machine and try to connect again. There could be few other items you must check and insure for a successful connection.

  • Make sure both the computers network property shows the connection as either domain or private.
  • Make sure you have File & Printer sharing enabled for the network

That’s all folks

RMAN on Windows | Backup & Restore 11g R2 database

11g R2? too late to post anything for 11g? Wait, there are thousands of Businesses still using Oracle database 10g. So let us see how RMAN could be simplified on Windows. I hardly see many articles explaining such for Windows platform in general.

Considering you have 11g database already installed & setup for Archive logging, we’ll start by setting up RMAN backup first, then try a restore routine on a different sever.

Like cron jobs on Linux environment, for Windows we will use Task Scheduler for RMAN backups. Here are couple of batch files we will be using for making RMAN backup on Windows.

run
{
ALLOCATE CHANNEL c1 DEVICE TYPE disk;
ALLOCATE CHANNEL c2 DEVICE TYPE disk;
ALLOCATE CHANNEL c3 DEVICE TYPE disk;
ALLOCATE CHANNEL c4 DEVICE TYPE disk;
crosscheck archivelog all;
crosscheck backup;
BACKUP AS COMPRESSED BACKUPSET DATABASE FORMAT 'D:\RMAN_BACKUP\PROD_comp_%d_ lvl0_%U' TAG "dailyfull_db_lvl0_bkp" INCLUDE CURRENT CONTROLFILE;
sql 'ALTER SYSTEM ARCHIVE LOG CURRENT';
BACKUP AS COMPRESSED BACKUPSET ARCHIVELOG ALL FORMAT 'D:\RMAN_BACKUP\archive_%d_lvl0_%U';
DELETE NOPROMPT archivelog all completed before 'sysdate-7';
backup current controlfile format 'D:\RMAN_BACKUP\bkpcontrol_file.ctl_%d_%T'               ;
DELETE NOPROMPT OBSOLETE RECOVERY WINDOW OF 7 DAYS;
RELEASE CHANNEL c1;
RELEASE CHANNEL c2;
RELEASE CHANNEL c3;
RELEASE CHANNEL c4;
}

Save this script as “rman_backup.cmd”. You can save it with any other name ending with .cmd or .bat extension. Make sure you change the name in the next script incase if you choose a name other than “rman_backup.cmd”. Please note, I am taking backup on “D:\RMAN_BACKUP” folder, you should change “D:\RMAN_BACKUP” with the exact location that is used for the backup!

Now, we will create another cmd file that will call the above script.

@echo off
For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%a-%%b)
For /f "tokens=1-2 delims=/:" %%a in ('time /t') do (set mytime=%%a%%b)
:: echo %mydate%_%mytime%

set filename="D:\RMAN_BACKUP\logs\%mydate%_%mytime%_rman_backup.log"
:: echo %filename%

rman target / nocatalog cmdfile='D:\scripts\rman_backup.cmd' log='%filename%'

Once again you can save this file with anytime, provided the extension is either .cmd or .bat. I saved this cmd file as “callrman.cmd”

Make sure the path ” D:\RMAN_BACKUP\logs” or equivalent exists prior running the scripts.

Now fire up Windows Task scheduler and create a basic job

That’s all. Everyday, at a said time, RMAN backups will be created and kept in the destination folder. We are using 7 days retention policy with the script file, so on the 8th day obsolete backups will be purged. Depending upon the disk space available, you should adjust the retention policy for your backups. Don’t forget to copy those backup pieces to an external medium to insure maximum availability during a crisis.

That completes the simplest form of Oracle RMAN backups on Windows platform.

RMAN Restore

Currently we are discussing about restoring the RMAN backup to same version of Oracle database. If you want to restore RMAN backup to a higher version of Oracle database, it will be an entirely different exercise.

RMAN backups are the fastest, easiest incase if you are doing it right. No hassles like creating tablespaces, schemas and then waiting hours for the import process to complete! The biggest size of the database I ever dealt with is 550GB and a server with 2×4 core processors, 16GB total memory restores the 140GB backup in less than 1.5 hours. I suggest you to start using RMAN backups the soonest possible regardless whether your database is just few megabytes in size.

Today we will see how to restore RMAN backup from Server A to Server B, ie, to a different physical server with a different database name.

It might sound bit unethical to ask you to create a new database using Oracle database creation wizard for this purpose, however this is what we will do for this exercise. This will save us some time figuring out setting up many other parameters for the new database at later stages.

So let us start.

Start DBCA and create a database with a database name that you prefer for the purpose, for eg: “ORCL”

Once the database created, shut it down & delete all the datafiles from the data store. For example, I had all my data files in the folder C:\oracle\oradata\orcl, where orcl is the database name!

Now copy the RMAN backups from Server A to Server B. I’ve copied only one day backups from Server A to Server B and make a note of the exact location where you copied the backup files. In my case, I copied the files to “C:\RMAN”

From an elevated command prompt start SQLPLUS as sysdba & start the database in non mounted mode.

Now, start another elevated command prompt and connect to RMAN in Auxiliary mode, for duplication of the database.

We are all set to restore the RMAN backup to Server B now. However, there are few things we have to insure to make a successful restoration. For example renaming the datafiles. Based on the new datastore location where you are restoring the database files, each data file should be renamed. Please refer the below sample script for the same.

run
{
ALLOCATE AUXILIARY CHANNEL c1 DEVICE TYPE disk;
ALLOCATE AUXILIARY CHANNEL c2 DEVICE TYPE disk;
ALLOCATE AUXILIARY CHANNEL c3 DEVICE TYPE disk;
ALLOCATE AUXILIARY CHANNEL c4 DEVICE TYPE disk;
duplicate database to "ORCL" backup location 'C:\RMAN' nofilenamecheck
db_file_name_convert=('D:\Oracle\oradata\PROD','C:\Oracle\oradata\orcl')
LOGFILE
GROUP 1 (
'C:\Oracle\oradata\orcl\redo01a.log',
'C:\Oracle\oradata\orcl\redo01b.log'
) SIZE 1000M ,
GROUP 2 (
'C:\Oracle\oradata\orcl\redo02a.log',
'C:\Oracle\oradata\orcl\redo02b.log'
) SIZE 1000M ,
GROUP 3 (
'C:\Oracle\oradata\orcl\redo03a.log',
'C:\Oracle\oradata\orcl\redo03b.log'
) SIZE 1000M ,
GROUP 4 (
'C:\Oracle\oradata\orcl\redo04a.log',
'C:\Oracle\oradata\orcl\redo04b.log'
) SIZE 1000M ;
RELEASE CHANNEL c1;
RELEASE CHANNEL c2;
RELEASE CHANNEL c3;
RELEASE CHANNEL c4;
}

As I am duplicating the database to existing one, I don’t have to go through the tedious process of changing the dbid or database name etc. Once the restore is done, all I need is to disable the archive logging and go online! We will see those in next few steps.

Please give attention to “db_file_name_convert“, Server A had the datafiles in the path “D:\oracle\oradata\PROD” and the Server B, we will be restoring the datafile to C:\oracle\ordata\orcl folder. So we must mention those changes here in the script. The same way we need to rename the logfiles and locations also. I hope the above script is self explanatory on that regard.

You may not need all those channel allocation for a small database, please adjust the number of cannels allocated as per your requirements. Give a try with less or more number of channels incase if you want to learn what happens :)

Execute the above script from the RMAN prompt.

If there are no errors, based on the size of the database & hardware resources RMAN will return to the prompt once the activities are finished.

Before doing anything else, we need to insure that the Archive logging is disabled for the newly restored database. Rush to the previous SQLPlus session that you started with nomount. This session is already disconnected, hence reconnect and shutdown immediate.

Now start the database in mount state and disable the archive logging.

Shutdown the database and restart normally.

That’s all, your Server B “orcl” has all the data from Server A “PROD” database now. If this is a production recovery, you can change the database name using “NID” utility, that is supported from Oracle database 9i onwards. Hope this helps few Oracle database beginners out there.

As we have restored full database with archive logs, there is no need to restore logs. Cross verify the database details

Cheers guys!

Oracle Application R12 | Using Microsoft Edge Chrome for versions 11 & 12.0.xx

After 25 years ever since it was launched, Windows 11 will be the first OS that is not shipping with Internet Explorer.

How does this matter to Businesses those use Oracle Application versions 11 & 12.0.xx? Well, currently Internet Explorer is the only one browser that allows to load Oracle JRE (NPAPI client) for Oracle Forms, on which much of the Oracle module rely.

Oracle Applications has patched the latest releases with a technology called JWS (Java Web Start), that let’s the users to download a jnlp file from the application and Oracle Java Run Time to start in desktop mode (without being loaded in a browser session) loading Oracle Forms. Well, this enhancement is not available for Application versions 11 & 12.0.xx

Microsoft was expecting a huge cry from the Businesses that use Oracle Applications/legacy implementations those cost millions of dollars and fine tuned for Internet Explorer. Cutting these businesses could mean loads for Microsoft, So they have integrated “IE Mode” into their chromium based “Edge browser”, which is the default browser on Windows 11. IE Mode makes Edge Chrome to “act” as if it were Internet Explorer for legacy Web based applications & loads NPAPI clients like JRE.

Today let us see how to configure Microsoft Edge Chrome for Oracle Applications.

Start Microsoft Edge Chrome & open “Settings”

Click on Default Browser & spend a moment to check currently set options.

Let us change few of those settings like shown below.

Let Internet Explorer open sites in Microsoft Edge -> Change to Allow

Allow sites to be reloaded in Internet Explorer mode ->Change to “Allow”. This will require you to restart the browser.

You must add the sites those you want to open in IE mode by clicking “Internet Explorer mode pages” Add button. Such pages will have maximum 30 days validity. Without, JRE will not load and will prompt you to download it from the default location.

Now, let us click the restart button & give it a try.

That’s all folks.

rsync | Excluding a subdirectory/folder

We’ve Oracle RMAN backups copied to a remote server everyday & those chunks are once again copied to a removable media to “avoid”, disasters.

After a revamp of backup path, I needed to adjust the rsync command within a shell script to exclude a folder from the source. Misunderstanding the instructions, the new modifications made the shell script to copy the backup chunks twice on the removable media!

Let us see what I did initially that caused the duplication

[root@orcl DAILYBKP]# cd /u03
[root@orcl u03]# mkdir -p folder1/erp/RMAN/DAILYBKP
[root@orcl u03]# mkdir -p folder1/sf1
[root@orcl u03]# mkdir -p folder1/sf2
[root@orcl u03]# mkdir -p folder1/sf3
[root@orcl u03]# mkdir -p folder2
[root@orcl u03]# touch folder1/erp/RMAN/DAILYBKP/r1.txt
[root@orcl u03]# touch folder1/erp/RMAN/DAILYBKP/r2.txt
[root@orcl u03]# touch folder1/sf2/r1.txt
[root@orcl u03]# touch folder1/sf3/r1.txt
[root@orcl u03]# rsync -avz --exclude '/u03/folder1/erp' /u03/folder1 /u03/folder2
sending incremental file list
folder1/
folder1/erp/
folder1/erp/RMAN/
folder1/erp/RMAN/DAILYBKP/
folder1/erp/RMAN/DAILYBKP/r1.txt
folder1/erp/RMAN/DAILYBKP/r2.txt
folder1/sf1/
folder1/sf2/
folder1/sf2/r1.txt
folder1/sf3/
folder1/sf3/r1.txt

The above example demonstrates the mistake that I made while “excluding” a folder from the source. The correct method to exclude a subdirectory or folder was as below

[root@orcl u03]# rsync -avz --exclude 'erp/' /u03/folder1 /u03/folder2
sending incremental file list
folder1/
folder1/sf1/
folder1/sf2/
folder1/sf2/r1.txt
folder1/sf3/
folder1/sf3/r1.txt

sent 263 bytes  received 74 bytes  674.00 bytes/sec
total size is 0  speedup is 0.00
[root@orcl u03]# cd folder2
[root@orcl folder2]# ls -ltrh
total 4.0K
drwxr-xr-x 5 root root 4.0K Aug 12 09:39 folder1
[root@orcl folder2]# cd folder1
[root@orcl folder1]# ls -ltrh
total 12K
drwxr-xr-x 2 root root 4.0K Aug 12 09:39 sf1
drwxr-xr-x 2 root root 4.0K Aug 12 09:40 sf2
drwxr-xr-x 2 root root 4.0K Aug 12 09:41 sf3
[root@orcl folder1]#

All I needed was to just mention the name of the subfolder that I needed to exclude, not the whole path. I’ve limited exposure to Linux and much of the OS activities are initiated on demand. This causes some interesting situations like the one above & definitely helps to learn something new!

Oracle 19c | Applying Patch

Much of the times I use latest Oracle technologies for learning & they hardly make to any of the PRODUCTION environments those I support at work. Recently I wanted to see how to patch Oracle 19c installation on Windows and to be frank, it was buttery smooth.

Let us quickly see how to apply a patch to a Windows installation of Oracle 19c database.

Shutdown all instances & Windows services for Oracle. Make sure you have taken adequate number of backups for the database(s).

Check you computer’s PATH variable. Insure you have %ORACLE_HOME%\perl\bin, in my case “D:\Oracle\19c\perl\bin” as the first entry for PERL.

This is how the PATH information before I make the above changes to it.

Here 11g 32Bit client is the first Oracle software in the PATH, we will modify it like below

Once the patching done, you can rollback the PATH variable according to your requirements.

Visit Oracle support and download the patch, the latest patch for Oracle Database 19c is “32409154”. Patch is only available to customers with a valid support contract.

Extract the archive.

I’ve extracted the archive within the Download folder and the path is

C:\Users\xxxxxxx\Downloads\Oracle19c_Patch\p32409154_190000_MSWIN-x86-64

Now open an elevated command prompt and switch to the folder with patch number as it’s name. Check the below image for details.

Now we are ready to apply the patch.

Call the opatch utility from here, like given example below.

Microsoft Windows [Version 10.0.19043.985]
(c) Microsoft Corporation. All rights reserved.

C:\Oracle19c_Patch\p32409154_190000_MSWIN-x86-64\32409154>d:\Oracle\19c\OPatch\opatch apply
Oracle Interim Patch Installer version 12.2.0.1.15
Copyright (c) 2021, Oracle Corporation.  All rights reserved.


Oracle Home       : d:\Oracle\19c
Central Inventory : C:\Program Files\Oracle\Inventory
   from           :
OPatch version    : 12.2.0.1.15
OUI version       : 12.2.0.7.0
Log file location : d:\Oracle\19c\cfgtoollogs\opatch\opatch2021-06-23_10-47-41AM_1.log

Verifying environment and performing prerequisite checks...
OPatch continues with these patches:   32409154

Do you want to proceed? [y|n]
y
User Responded with: Y
All checks passed.

Please shutdown Oracle instances running out of this ORACLE_HOME on the local system.
(Oracle Home = 'd:\Oracle\19c')


Is the local system ready for patching? [y|n]
y
User Responded with: Y
Backing up files...
Applying interim patch '32409154' to OH 'd:\Oracle\19c'
ApplySession: Optional component(s) [ oracle.assistants.usm, 19.0.0.0.0 ] , [ oracle.rdbms.ic, 19.0.0.0.0 ] , [ oracle.rdbms.tg4ifmx, 19.0.0.0.0 ] , [ oracle.has.deconfig, 19.0.0.0.0 ] , [ oracle.swd.oui, 19.0.0.0.0 ] , [ oracle.has.cfs, 19.0.0.0.0 ] , [ oracle.rdbms.tg4tera, 19.0.0.0.0 ] , [ oracle.network.gsm, 19.0.0.0.0 ] , [ oracle.network.cman, 19.0.0.0.0 ] , [ oracle.rdbms.tg4msql, 19.0.0.0.0 ] , [ oracle.ons.daemon, 19.0.0.0.0 ] , [ oracle.options.olap.awm, 19.0.0.0.0 ] , [ oracle.rdbms.tg4db2, 19.0.0.0.0 ] , [ oracle.assistants.asm, 19.0.0.0.0 ] , [ oracle.usm, 19.0.0.0.0 ] , [ oracle.swd.oui.core.min, 19.0.0.0.0 ] , [ oracle.tomcat.crs, 19.0.0.0.0 ] , [ oracle.options.olap, 19.0.0.0.0 ] , [ oracle.has.crs, 19.0.0.0.0 ] , [ oracle.tfa, 19.0.0.0.0 ] , [ oracle.has.cvu, 19.0.0.0.0 ] , [ oracle.rdbms.tg4sybs, 19.0.0.0.0 ]  not present in the Oracle Home or a higher version is found.

Patching component oracle.sdo, 19.0.0.0.0...

Patching component oracle.rdbms.rman, 19.0.0.0.0...

Patching component oracle.aspnet_2, 19.0.0.0.0...

Patching component oracle.dbjava.ic, 19.0.0.0.0...

Patching component oracle.ons, 19.0.0.0.0...

Patching component oracle.ntoramts, 19.0.0.0.0...

Patching component oracle.rdbms.dbscripts, 19.0.0.0.0...

Patching component oracle.nlsrtl.rsf, 19.0.0.0.0...

Patching component oracle.xdk.parser.java, 19.0.0.0.0...

Patching component oracle.rdbms, 19.0.0.0.0...

Patching component oracle.blaslapack, 19.0.0.0.0...

Patching component oracle.rdbms.oci, 19.0.0.0.0...

Patching component oracle.assistants.acf, 19.0.0.0.0...

Patching component oracle.duma, 19.0.0.0.0...

Patching component oracle.sdo.locator.jrf, 19.0.0.0.0...

Patching component oracle.tfa.db, 19.0.0.0.0...

Patching component oracle.ldap.security.osdt, 19.0.0.0.0...

Patching component oracle.ctx.atg, 19.0.0.0.0...

Patching component oracle.xdk.rsf, 19.0.0.0.0...

Patching component oracle.precomp.common, 19.0.0.0.0...

Patching component oracle.dbjava.jdbc, 19.0.0.0.0...

Patching component oracle.rdbms.hsodbc, 19.0.0.0.0...

Patching component oracle.sqlplus.ic, 19.0.0.0.0...

Patching component oracle.oracore.rsf, 19.0.0.0.0...

Patching component oracle.rsf, 19.0.0.0.0...

Patching component oracle.precomp.common.core, 19.0.0.0.0...

Patching component oracle.network.client, 19.0.0.0.0...

Patching component oracle.precomp.lang, 19.0.0.0.0...

Patching component oracle.install.deinstalltool, 19.0.0.0.0...

Patching component oracle.ctx, 19.0.0.0.0...

Patching component oracle.dbjava.ucp, 19.0.0.0.0...

Patching component oracle.javavm.client, 19.0.0.0.0...

Patching component oracle.network.listener, 19.0.0.0.0...

Patching component oracle.ntoledb.odp_net_2, 19.0.0.0.0...

Patching component oracle.rdbms.util, 19.0.0.0.0...

Patching component oracle.rdbms.lbac, 19.0.0.0.0...

Patching component oracle.usm.deconfig, 19.0.0.0.0...

Patching component oracle.assistants.server, 19.0.0.0.0...

Patching component oracle.rdbms.deconfig, 19.0.0.0.0...

Patching component oracle.ntoledb, 19.0.0.0.0...

Patching component oracle.has.common, 19.0.0.0.0...

Patching component oracle.assistants.deconfig, 19.0.0.0.0...

Patching component oracle.ldap.rsf, 19.0.0.0.0...

Patching component oracle.ovm, 19.0.0.0.0...

Patching component oracle.has.db, 19.0.0.0.0...

Patching component oracle.rdbms.plsql, 19.0.0.0.0...

Patching component oracle.precomp.rsf, 19.0.0.0.0...

Patching component oracle.xdk.xquery, 19.0.0.0.0...

Patching component oracle.javavm.server, 19.0.0.0.0...

Patching component oracle.xdk, 19.0.0.0.0...

Patching component oracle.dbdev, 19.0.0.0.0...

Patching component oracle.sdo.locator, 19.0.0.0.0...

Patching component oracle.rdbms.install.plugins, 19.0.0.0.0...

Patching component oracle.rdbms.olap, 19.0.0.0.0...

Patching component oracle.rdbms.scheduler, 19.0.0.0.0...

Patching component oracle.rdbms.rsf.ic, 19.0.0.0.0...

Patching component oracle.ldap.owm, 19.0.0.0.0...

Patching component oracle.rdbms.rsf, 19.0.0.0.0...

Patching component oracle.mgw.common, 19.0.0.0.0...

Patching component oracle.network.rsf, 19.0.0.0.0...

Patching component oracle.oraolap, 19.0.0.0.0...

Patching component oracle.clrintg.ode_net_2, 19.0.0.0.0...

Patching component oracle.rdbms.dv, 19.0.0.0.0...

Patching component oracle.has.rsf, 19.0.0.0.0...

Patching component oracle.odbc.ic, 19.0.0.0.0...

Patching component oracle.sqlplus, 19.0.0.0.0...

Patching component oracle.has.common.cvu, 19.0.0.0.0...
Patch 32409154 successfully applied.
Log file location: d:\Oracle\19c\cfgtoollogs\opatch\opatch2021-06-23_10-47-41AM_1.log

OPatch succeeded.

As usual, based on your computer’s hardware capabilities, the patch would finish sooner or later. There will be 2 prompts those you need to say Yes in order to progress the patching.

Simple & neat right? Share your experience in the comments area.

Oracle PL/SQL | Exiting without executing rest of the code block

One of the major confusions for a PL/SQL programming beginners is how to exit a code block when a specific exception happens. Today we will see how we can handle these situation using user defined exceptions.

A developer can define as many exceptions for the code block and raise them as and when needed, than the default exception block for a BEGIN..END; block

Here I am trying to explain how a PL/SQL developer could exit the execution as soon as the first exception happens.

SET SERVEROUTPUT ON;

DECLARE
    l_number NUMBER := 11;
    myexp EXCEPTION;
BEGIN
    BEGIN
        IF l_number = 10 THEN
            RAISE myexp;
        END IF;
    EXCEPTION
        WHEN myexp THEN
            dbms_output.put_line('Okay, let us exit');
            RETURN;
    END;

    BEGIN
        dbms_output.put_line('Looks like there were no exceptions, let us show this!');
    END;
END;

The above example is trying to demonstrate how the exceptions are handled by dividing the code into multiple BEGIN..END blocks. So here I am doing a check whether the “l_number” is 10 and to raise an user defined exception and by merely calling RETURN exit the complete PL/SQL block! As simple as it looks here.

Give it a try by change the l_number value to 10 at the declaration level and see yourself. Happy coding!

ASP.NET Core | HttpContext | Get current windows username

Special Note: If you want ONLY get the currently logged in Windows username (useful for Windows domain networks) all you need is to change the website’s authentication to Windows & calling “User.Identity.Name”. The below example mostly looking at how to implement HttpContext in a project.

Recently we decided to retire our Classic ASP intranet application & opted ASP.NET Core for the upgrade. As a Business, we are totally in to Oracle technologies and hardly had much exposure towards .NET development. With the help of netizens, blogs and forums, we figured out the basics of CRUD operations using ASP.NET Core. However, were totally bowled out while getting currently logged in Windows usernames (domain accounts) for the application. Then we came across this post

Using the above post, we managed to figure out way to “get” the Windows username using HttpContext & realizing the above link (although helped us), was too technical for beginners and decided to make a post that simplifies the instructions further a level. So, here it is.

Please note, I am using 2019 community editions for both Visual Studio and MS SQL Database. If you are using a previous versions of Visual Studio, may not able to open the sample solution provided with this post. A note of caution. We are as fresh as possible with ASP.NET Core development & would appreciate pointing out our mistakes instead lamenting. Thank you.

So let us start creating a new ASP.NET Core project that uses C# (ASP.NET Core Web App (Model-View-Controller)

Give a meaningful name for your solution

Select “Windows Authentication” for your solution (must)

Your project explorer should look like this

Open Startup.cs file and modify “ConfigureServices” method like below

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            //Rajesh Added the below
            services.AddHttpContextAccessor();


        }

To keep it clean and simple, we will use a class specific to establish HttpContext.

Add a new class to Models, and let us call it “WindowsUserClass”

Add Microsoft.AspNetCore.Http namespace to the class before adding the below properties initializing the class.

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace GetWindowsUserName.Models
{
    public class WindowsUserClass
    {

        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly string _userName;
        public WindowsUserClass(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
            _userName = httpContextAccessor.HttpContext.User.Identity.Name;
        }

        public string GetUserName()
        {
            return _userName;
        }
    }
}

We will use the Controller construct dependency injection (read it, going to be difficult to understand if you are a beginner like us :) ) to initialize the WindowsUserClass by passing IHttpContextAccessor as a parameter.

HomeController constructor before adding IHttpContextAccessor

After modification

You have to add Microsoft.AspNetCore.Http namespace to the controller also.

Now we should able to call the GetUserName() function from WindowsUserClass from the HomeController! Let us give it a try

We’ll modify the Index view call slightly by passing the “yourusername” string.

We’ll modify “Index” view to show our Windows username now. You can call the view directly referring the GetUserName() function also. That will avoid an additional variable declaration.

return View("Index", windowsUserClass.GetUserName());
@model string
@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome @Model</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

Before executing your project, we must change one more existing file!

Open launchSettings.json file and modify the content like below

You must change the windowsAuthentication string value to “true” and anonymousAuthentication to “false”. Save the changes.

You can build the solution and run to debug to check whether the solution is working as per expectations. One of the most important things you MUST understand now, for HttpContext to fetch you the intended results, your website should not be configured for Anonymous authentication. Here is the screen once after you enter the windows username and password when prompted!

You must change the website’s authentication methods prior publishing using IIS. For example

Hope this helps few out there! If the situation permits, I might record a video with instructions soon for the same. Stay tuned folks. For those who cannot open the Visual Studio 2019 solution using their versions of VS, find the page codes below. This way of calling HttpContextAccessor is supported from ASP.NET Core 3.1

Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace GetWindowsUserName
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            //Rajesh Added the below
            services.AddHttpContextAccessor();


        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

HomeController.cs

using GetWindowsUserName.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace GetWindowsUserName.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        WindowsUserClass windowsUserClass = null;
        public HomeController(ILogger<HomeController> logger, IHttpContextAccessor httpContextAccessor)
        {
            _logger = logger;

            windowsUserClass = new WindowsUserClass(httpContextAccessor);
        }

        public IActionResult Index()
        {

            string yourusername = windowsUserClass.GetUserName();

            return View("Index",yourusername);
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

WindowsUserClass.cs

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace GetWindowsUserName.Models
{
    public class WindowsUserClass
    {

        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly string _userName;
        public WindowsUserClass(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
            _userName = httpContextAccessor.HttpContext.User.Identity.Name;
        }

        public string GetUserName()
        {
            return _userName;
        }
    }
}

You may download the sample solution from this link.

Microsoft ODBC Driver 17: A previous installation required a reboot of the machine for changes to take effect.

Today I was trying to install SSMS SQL Server Management Studio 18.9.1 & the installation was stopped with a message “Microsoft ODBC Driver 17: A previous installation required a reboot of the machine for changes to take effect”

Abiding, I went ahead to reboot & instead pressed the shutdown button. After restarting the PC, tried to install SSMS once again and the installer gave up mentioning the same message.

All I needed was “reboot” the machine. Microsoft is sometimes, grr.

Publish nopCommerce using IIS

nopCommerce is one of the free and open-source eCommerce platforms that you can instantly publish and go online with. Please follow the below steps to publish nopCommerce using IIS

Download nopCommerce. If you are not going to develop the suite further, better download package without source code.

Unzip the package.

Based on your choice, you can move this folder to C:\inetpub\wwwroot\. For example, I renamed the folder and current path for nopCommerce is C:\inetpub\wwwroot\nop

You can have this folder anywhere in your computer. Just make sure that you changed the permissions as specified below. Full control is only recommended for development environments.

The most important element of publishing nopCommerce successfully is how you setup the folder access to IIS_IUSRS. Right click on the folder and change the permissions to either Full Control or Read, Write. Failing will fail the nopCommerce suite from launching. You will keep getting “HTTP Error 500.30 – ASP.NET Core app failed to start” until you change the folder permissions.

Now, install DOTNET Core Hosting Bundle. While writing this article, the latest stable version was 5.0.5 and you can download the same from here. Just make sure that you download the correct Hosting Bundle.

Install the bundle, that takes hardly couple of minutes. Once the bundle is installed, restart the IIS service.

Create a database on your SQL Server, exclusively dedicated for nopCommerce. You have to provide these details while setting up nopCommerce for the first time. You may skip creating the database yourself, as the installer offers to create a new database during the installation. However, you must be ready with the connection credentials. nopCommerce supports both integrated security and user/password based security approaches.

Create a new Application pool. Make sure the Application pool has .NET CLR Version set as “No Managed Code”. I can confirm that nopCommerce works with .NET CLR Version set as well. However, all the documents are asking you to setup “No Managed Code”

Finally you can publish nopCommerce. You can either publish nopCommerce as an application with an existing website or create a new website and publish it. For my development machine, I opted to publish it with existing website.

Open your favorite browser and point to http://localhost/nop or http://localhost based on how you published the application & you must be taken the nopCommerce installation. Follow the instructions & I suggest you to select sample items during installation. This will give you an idea of how the items are presented over your portal. You can remove those sample items anytime. Make sure that you will enable the https switch in the application before implementing https for the application with IIS.

That’s all folks.